Thread Tools Display Modes
03/09/23, 11:48 PM   #1
sinnereso
AddOn Author - Click to view addons
Join Date: Oct 2022
Posts: 244
Question 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

Last edited by sinnereso : 03/09/23 at 11:52 PM.
  Reply With Quote
03/10/23, 04:06 AM   #2
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 4,912
Why don't you just use LibCustomMenu as it integrates and was build EXACTLY for that purpose?
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:
  1. if not LibCustomMenu then return end

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.

Last edited by Baertram : 03/10/23 at 04:08 AM.
  Reply With Quote
03/10/23, 04:17 AM   #3
sinnereso
AddOn Author - Click to view addons
Join Date: Oct 2022
Posts: 244
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
  Reply With Quote
03/10/23, 04:53 AM   #4
sinnereso
AddOn Author - Click to view addons
Join Date: Oct 2022
Posts: 244
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()
	if not LibCustomMenu then return end
	AddCustomMenuItem("Save to MyAddon", MyAddon.SavePlayer())
	--or
	lib:RegisterGuildRosterContextMenu(MyAddon.SavePlayer(), lib.CATEGORY_LATE, ...)
	return
end
i realize this is nowhere close to working as i haven't told it which menu and what to save.

Last edited by sinnereso : 03/10/23 at 05:13 AM.
  Reply With Quote
03/10/23, 06:32 AM   #5
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 4,912
Originally Posted by sinnereso View Post
## OptionalDependsOn: LibCustomMenu>=680 <<< ive found this in another addon but no idea what the number means... line#?
Check the WIKI for such questions, it explains what the manifes txt file contains and why there are such things like >= version etc. for libraries
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:
  1. if LibCustomMenu ~= nil then
  2.    local function func(rowData)
  3.     ---rowData contains the row's data table of the right clicked guild roster row
  4.     --so get whatever you need from rowData
  5.     --You coudl add rowData to your global variable MyAddon._rowData and the inspect MyAddon._rowData with merTorchbug or zgoo ingame to see what it provides. I think there is a displayName in the rowData and maybe the charatcterName, a memberIndex of that row, etc.
  6.        MyAddon.SavePlayer(rowData.displayName) --only an example, dunno if displayName exists in there
  7.    end
  8.    --category can be any of the categories of the lib do define if teh contetx menu entyr should be added early (at the top of the context menu -> don't do that as all vanilla contetx menu entries should stay there so users do not get confused...) or at the bottom of the context menu.
  9. --[[
  10. category
  11. lib.CATEGORY_EARLY
  12. lib.CATEGORY_PRIMARY
  13. lib.CATEGORY_SECONDARY
  14. lib.CATEGORY_TERTIARY
  15. lib.CATEGORY_QUATERNARY
  16. lib.CATEGORY_LATE
  17. ]]
  18.  
  19.    local category = LibCustomMenu.CATEGORY_LATE
  20.    LibCustomMenu:RegisterGuildRosterContextMenu(myFunc, category)
  21. end
  22.  
  23. For the other context menu at the chat etc. check the description, it works about the same like teh guidl roster.
  24. 1 function needs to be registered which is called as the chat entry is right clicked and you define the callback function of your addon and the category etc.

Last edited by Baertram : 03/10/23 at 06:40 AM.
  Reply With Quote
03/10/23, 06:57 AM   #6
sinnereso
AddOn Author - Click to view addons
Join Date: Oct 2022
Posts: 244
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.
  Reply With Quote
03/10/23, 08:28 AM   #7
sinnereso
AddOn Author - Click to view addons
Join Date: Oct 2022
Posts: 244
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
	local function func(rowData)
		   MyAddon.SavePlayerContext(rowData.displayName)
	end
        local category = LibCustomMenu.CATEGORY_LATE
	LibCustomMenu:RegisterGuildRosterContextMenu(MyAddon.SavePlayerContext, category)
end
seems more confusing not less to me.. im new at this so i like or even need to follow everystep

Last edited by sinnereso : 03/10/23 at 02:27 PM.
  Reply With Quote
03/10/23, 03:03 PM   #8
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 4,912
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!
  Reply With Quote
03/10/23, 03:16 PM   #9
sinnereso
AddOn Author - Click to view addons
Join Date: Oct 2022
Posts: 244
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()
if LibCustomMenu ~= nil then
		local function func(rowData)
		      MyAddon.AddMenuContext(rowData.playerName)
		end
		local category = LibCustomMenu.CATEGORY_LATE
		LibCustomMenu:RegisterGuildRosterContextMenu(MyAddon.AddMenuContext, category)
	end

function MyAddon.AddMenuContext(playerName) <<<<<< this is adding the menu item but error clicking in guild menu
	AddCustomMenuItem("MyAddon Save",  MyAddon.SavePlayerContext(playerName))
end

function MyAddon.SavePlayerContext(playerName) <<<<<<<<<its not liking this section at all yet
	--local playerToBeSaved = playerName
        --MyAddon.savedVariables.savedPlayer = playerToBeSaved
	--df("|c6666FF[MyAddon]|r Saving: %s", playerToBeSaved)
end

Last edited by sinnereso : 03/10/23 at 03:23 PM.
  Reply With Quote
03/10/23, 04:16 PM   #10
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 4,912
Well Ive never used a callback
And how did you let your addon properly load then if you never did use a callback so far?
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:
  1. AddCustomMenuItem("MyAddon Save",  MyAddon.SavePlayerContext(playerName))
  2. end

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:
  1. AddCustomMenuItem("MyAddon Save",  function() MyAddon.SavePlayerContext(playerName) end)

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.

Last edited by Baertram : 03/10/23 at 04:20 PM.
  Reply With Quote
03/10/23, 04:36 PM   #11
sinnereso
AddOn Author - Click to view addons
Join Date: Oct 2022
Posts: 244
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()
if LibCustomMenu ~= nil then
		local function func(rowData)
			MyAddon.AddMenuContext(rowData.displayName)
		end
		local category = LibCustomMenu.CATEGORY_LATE
		LibCustomMenu:RegisterGuildRosterContextMenu(MyAddon.AddMenuContext, category)
end

function MyAddon.AddMenuContext()
	AddCustomMenuItem("MyAddon Save",  function() MyAddon.SavePlayerContext(rowData.displayName) end)
end

function MyAddon.SavePlayerContext()
	--local playerToBeSaved = rowData.displayName
	df("|c6666FF[MyAddon]|r Saving: %s", rowData.displayName)
end

Last edited by sinnereso : 03/10/23 at 05:00 PM.
  Reply With Quote
03/10/23, 04:40 PM   #12
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 4,912
https://www.lua.org/pil/6.html

Maybe that will explain it (anonymous functions e.g.) with more details
  Reply With Quote
03/10/23, 07:55 PM   #13
sinnereso
AddOn Author - Click to view addons
Join Date: Oct 2022
Posts: 244
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.
  Reply With Quote
03/11/23, 04:37 AM   #14
sinnereso
AddOn Author - Click to view addons
Join Date: Oct 2022
Posts: 244
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
		local function func(rowData)
			MyAddon.AddMenuContext(rowdata.displayName)
		end
		local function func(playerName, rawName)
			MyAddon.AddMenuContext(playerName, rawName)
		end
		local category = LibCustomMenu.CATEGORY_LATE
		LibCustomMenu:RegisterGuildRosterContextMenu(MyAddon.AddMenuContext, category)
		LibCustomMenu:RegisterPlayerContextMenu(MyAddon.AddMenuContext, category)
end
  Reply With Quote
03/11/23, 05:43 AM   #15
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 4,912
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, ...)

Last edited by Baertram : 03/11/23 at 05:49 AM.
  Reply With Quote
03/11/23, 06:06 AM   #16
sinnereso
AddOn Author - Click to view addons
Join Date: Oct 2022
Posts: 244
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
  Reply With Quote
03/12/23, 03:58 AM   #17
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 4,912
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.
  Reply With Quote
03/12/23, 05:23 AM   #18
sinnereso
AddOn Author - Click to view addons
Join Date: Oct 2022
Posts: 244
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.
  Reply With Quote
03/12/23, 06:07 AM   #19
Baertram
Super Moderator
 
Baertram's Avatar
WoWInterface Super Mod
AddOn Author - Click to view addons
Join Date: Mar 2014
Posts: 4,912
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.
  Reply With Quote
03/26/23, 04:19 PM   #20
sinnereso
AddOn Author - Click to view addons
Join Date: Oct 2022
Posts: 244
Question

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--
local category = LibCustomMenu.CATEGORY_LATE--<<< context menu stuff
LibCustomMenu:RegisterGuildRosterContextMenu(MyAddon.AddGGFContext, category)
LibCustomMenu:RegisterFriendsListContextMenu(MyAddon.AddGGFContext, category)
LibCustomMenu:RegisterGroupListContextMenu(MyAddon.AddGGFContext, category)
MyAddon:CreateSettingsWindow()

-- LibAddonMenu SETTINGS PANEL TEXT FIELD --
{
		type = "description",
		text = "Saved Player:  " .. tostring(MyAddon.savedVariables.savedPlayer),
		reference = "MyAddon_SETTINGS_SAVEDPLAYER_TEXT",
		width = "half",
},

------ Save player functions ------
241-function MyAddon.AddGGFContext(data)
242->	AddCustomMenuItem("Save to MyAddon", function() MyAddon.SavePlayer(data.displayName) end)
243-end

245-function MyAddon.SavePlayer(displayName)
246	MyAddon.savedVariables.savedPlayer = displayName
247	df("|c6666FF[MyAddon]|r Saving: " .. tostring(displayName))-- WORKING FINE
248->	MyAddon_SETTINGS_SAVEDPLAYER_TEXT.data.text = "Saved Player: " .. tostring(displayName)-- ERRORS APPEAR TO BE HERE AND BELOW REPORTING NIL VALUE FOR IM ASSUMING "displayName"
249-	MyAddon_SETTINGS_SAVEDPLAYER_TEXT:UpdateValue()
250-end
ERRORS:
Code:
user:/AddOns/MyAddon/MyAddon.lua:248: attempt to index a nil value
stack traceback:
user:/AddOns/MyAddon/MyAddon.lua:248: in function 'MyAddon.SavePlayer'
user:/AddOns/MyAddon/MyAddon.lua:242: in function 'OnSelect'
/EsoUI/Libraries/ZO_ContextMenus/ZO_ContextMenus.lua:476: in function 'ZO_Menu_ClickItem'
user:/AddOns/LibCustomMenu/LibCustomMenu.lua:604: in function 'MouseUp'

Last edited by sinnereso : 03/26/23 at 05:18 PM.
  Reply With Quote

ESOUI » Developer Discussions » Lua/XML Help » Add guild/friend lists context menu item

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