diff --git a/esoui/ingame/lfg/gamepad/zo_activityfindertemplate_gamepad.lua b/esoui/ingame/lfg/gamepad/zo_activityfindertemplate_gamepad.lua
new file mode 100644
index 0000000..0821092
--- /dev/null
+++ b/esoui/ingame/lfg/gamepad/zo_activityfindertemplate_gamepad.lua
@@ -0,0 +1,487 @@
+ZO_GAMEPAD_ACTIVITY_FINDER_BACKGROUND_TEXTURE_SQUARE_DIMENSION = 1024
+ZO_GAMEPAD_ACTIVITY_FINDER_BACKGROUND_TEXTURE_COORD_RIGHT = ZO_GAMEPAD_QUADRANT_2_3_CONTENT_BACKGROUND_WIDTH / ZO_GAMEPAD_ACTIVITY_FINDER_BACKGROUND_TEXTURE_SQUARE_DIMENSION
+
+local NAVIGATION_MODES =
+{
+ CATEGORIES = 1,
+ RANDOM_ENTRIES = 2,
+ SPECIFIC_ENTRIES = 3,
+}
+
+local RANDOM_CATEGORY_ICON = "EsoUI/Art/LFG/Gamepad/gp_LFG_menuIcon_Random.dds"
+
+ZO_ActivityFinderTemplate_Gamepad = ZO_Object.MultiSubclass(ZO_ActivityFinderTemplate_Shared, ZO_Gamepad_ParametricList_Screen)
+
+function ZO_ActivityFinderTemplate_Gamepad:New(...)
+ local manager = ZO_Object.New(self)
+ manager:Initialize(...)
+ return manager
+end
+
+function ZO_ActivityFinderTemplate_Gamepad:Initialize(dataManager, categoryData)
+ local control = CreateControlFromVirtual(dataManager:GetName() .. "_Gamepad", GuiRoot, "ZO_ActivityFinderTemplateTopLevel_Gamepad")
+ ZO_ActivityFinderTemplate_Shared.Initialize(self, control, dataManager, categoryData)
+ local ACTIVATE_LIST_ON_SHOW = true
+ ZO_Gamepad_ParametricList_Screen.Initialize(self, control, ZO_GAMEPAD_HEADER_TABBAR_CREATE, ACTIVATE_LIST_ON_SHOW, self.scene)
+ self:SetListsUseTriggerKeybinds(true)
+ self:InitializeLists()
+end
+
+function ZO_ActivityFinderTemplate_Gamepad:InitializeControls()
+ ZO_ActivityFinderTemplate_Shared.InitializeControls(self, "ZO_ActivityFinderTemplateRewardTemplate_Gamepad")
+ self.headerControl = self.control:GetNamedChild("MaskContainerHeaderContainerHeader")
+end
+
+function ZO_ActivityFinderTemplate_Gamepad:InitializeFragment()
+ local categoryData = self.categoryData
+ local scene = ZO_Scene:New(categoryData.sceneName, SCENE_MANAGER)
+ local fragment = ZO_SimpleSceneFragment:New(self.control)
+ fragment:SetHideOnSceneHidden(true)
+ scene:AddFragment(fragment)
+
+ self.scene = scene
+ self.fragment = fragment
+ self.singularFragment = ZO_FadeSceneFragment:New(self.singularSection)
+ ZO_ACTIVITY_FINDER_ROOT_GAMEPAD:AddCategory(categoryData)
+end
+
+function ZO_ActivityFinderTemplate_Gamepad:InitializeFilters()
+ self.categoryHeaderData =
+ {
+ titleText = self.categoryData.name,
+ }
+
+ local modes = self.dataManager:GetFilterModeData()
+ local randomEntryDatas = {}
+
+ --Init potential randoms
+ for _, activityType in ipairs(modes:GetActivityTypes()) do
+ local randomInfo = modes:GetRandomInfo(activityType)
+ if randomInfo and DoesLFGActivityHasAllOption(activityType) then
+ local activityName = zo_strformat(SI_ACTIVITY_FINDER_RANDOM_TITLE_FORMAT, GetString("SI_LFGACTIVITY", activityType))
+ local minGroupSize, maxGroupSize = ZO_ACTIVITY_FINDER_ROOT_MANAGER:GetGroupSizeRangeForActivityType(activityType)
+ local entryData = ZO_GamepadEntryData:New(activityName, RANDOM_CATEGORY_ICON)
+ entryData.data =
+ {
+ activityType = activityType,
+ nameGamepad = activityName,
+ description = randomInfo.description,
+ descriptionTextureGamepad = randomInfo.gamepadBackground,
+ isRandom = true,
+ minGroupSize = minGroupSize,
+ maxGroupSize = maxGroupSize,
+ }
+ entryData:SetIconTintOnSelection(true)
+ table.insert(randomEntryDatas, entryData)
+ end
+ end
+
+ self.randomEntryDatas = randomEntryDatas
+ self.randomHeaderData =
+ {
+ titleText = modes:GetRandomFilterName(),
+ }
+
+ self:RefreshSpecificFilters()
+end
+
+function ZO_ActivityFinderTemplate_Gamepad:InitializeLists()
+ --When we have "random" entries, we have the user drill down into a further subcategory
+ --Where they can either select from a list of random activitiy types, or a list of specific activities
+ if #self.randomEntryDatas > 0 then
+ self.categoryList = self:GetMainList()
+ self:AddRolesMenuEntry(self.categoryList)
+ local filterModes = self.dataManager:GetFilterModeData()
+
+ local randomEntryData = ZO_GamepadEntryData:New(filterModes:GetRandomFilterName(), RANDOM_CATEGORY_ICON)
+ randomEntryData.data =
+ {
+ isRandom = true,
+ }
+ randomEntryData:SetIconTintOnSelection(true)
+ self.categoryList:AddEntry("ZO_GamepadMenuEntryTemplate", randomEntryData)
+
+ local specificEntryData = ZO_GamepadEntryData:New(filterModes:GetSpecificFilterName(), self.categoryData.menuIcon)
+ specificEntryData.data =
+ {
+ isRandom = false,
+ }
+ specificEntryData:SetIconTintOnSelection(true)
+
+ self.categoryList:AddEntry("ZO_GamepadMenuEntryTemplate", specificEntryData)
+ self.categoryList:Commit()
+
+ self.entryList = self:AddList("Entries")
+ self.hasCategories = true
+
+ local categoryListControl = self.categoryList:GetControl()
+ categoryListControl:SetAnchor(TOPLEFT, self.headerControl, BOTTOMLEFT, 0, ZO_GAMEPAD_ROLES_BAR_ADDITIONAL_HEADER_SPACE)
+ else
+ self.entryList = self:GetMainList()
+ self.hasCategories = false
+ end
+
+ self.entryList:AddDataTemplate("ZO_GamepadItemSubEntryTemplate", ZO_SharedGamepadEntry_OnSetup, ZO_GamepadMenuEntryTemplateParametricListFunction)
+ self.entryList:AddDataTemplateWithHeader("ZO_GamepadItemSubEntryTemplate", ZO_SharedGamepadEntry_OnSetup, ZO_GamepadMenuEntryTemplateParametricListFunction, nil, "ZO_GamepadMenuEntryHeaderTemplate")
+ local entryListControl = self.entryList:GetControl()
+ entryListControl:SetAnchor(TOPLEFT, self.headerControl, BOTTOMLEFT, 0, ZO_GAMEPAD_ROLES_BAR_ADDITIONAL_HEADER_SPACE)
+end
+
+function ZO_ActivityFinderTemplate_Gamepad:InitializeSingularPanelControls(rewardsTemplate)
+ ZO_ActivityFinderTemplate_Shared.InitializeSingularPanelControls(self, rewardsTemplate)
+
+ self.lockControl = self.singularSection:GetNamedChild("Lock")
+ self.lockReasonLabel = self.lockControl:GetNamedChild("Reason")
+end
+
+function ZO_ActivityFinderTemplate_Gamepad:RegisterEvents()
+ ZO_ActivityFinderTemplate_Shared.RegisterEvents(self)
+ ZO_ACTIVITY_FINDER_ROOT_MANAGER:RegisterCallback("OnSelectionsChanged", function(...) self:RefreshSelections(...) end)
+end
+
+function ZO_ActivityFinderTemplate_Gamepad:OnDeferredInitialize()
+ self.singularFragmentGroup = { self.singularFragment, GAMEPAD_NAV_QUADRANT_2_3_BACKGROUND_FRAGMENT }
+ self.isShowingSingularPanel = false
+end
+
+function ZO_ActivityFinderTemplate_Gamepad:SetupList(list)
+ ZO_Gamepad_ParametricList_Screen.SetupList(self, list)
+
+ local function OnSelectedEntry(_, selectedData)
+ if selectedData.data.isRoleSelector then
+ GAMEPAD_GROUP_ROLES_BAR:Activate()
+ else
+ GAMEPAD_GROUP_ROLES_BAR:Deactivate()
+ end
+
+ KEYBIND_STRIP:UpdateKeybindButtonGroup(self.keybindStripDescriptor)
+ self:RefreshSingularSectionPanel()
+ end
+
+ list:SetOnSelectedDataChangedCallback(OnSelectedEntry)
+ list:SetDefaultSelectedIndex(2) --Don't select roles by default
+end
+
+function ZO_ActivityFinderTemplate_Gamepad:InitializeKeybindStripDescriptors()
+ self.keybindStripDescriptor =
+ {
+ alignment = KEYBIND_STRIP_ALIGN_LEFT,
+
+ -- Select
+ {
+ name = GetString(SI_GAMEPAD_SELECT_OPTION),
+
+ keybind = "UI_SHORTCUT_PRIMARY",
+
+ callback = function()
+ local entryData = self:GetCurrentList():GetTargetData().data
+ if entryData.isRoleSelector then
+ GAMEPAD_GROUP_ROLES_BAR:ToggleSelected()
+ else
+ if self.navigationMode == NAVIGATION_MODES.CATEGORIES then
+ local navigationMode = entryData.isRandom and NAVIGATION_MODES.RANDOM_ENTRIES or NAVIGATION_MODES.SPECIFIC_ENTRIES
+ self:SetNavigationMode(navigationMode)
+ elseif self.navigationMode == NAVIGATION_MODES.RANDOM_ENTRIES then
+ ZO_ACTIVITY_FINDER_ROOT_MANAGER:ToggleActivityTypeSelected(entryData.activityType)
+ else
+ ZO_ACTIVITY_FINDER_ROOT_MANAGER:ToggleLocationSelected(entryData)
+ end
+ end
+ end,
+
+ enabled = function()
+ local currentList = self:GetCurrentList()
+ if currentList then
+ local targetData = currentList:GetTargetData()
+ return targetData and targetData:IsEnabled()
+ end
+ return false
+ end,
+ },
+
+ --Back
+ {
+ name = GetString(SI_GAMEPAD_BACK_OPTION),
+
+ keybind = "UI_SHORTCUT_NEGATIVE",
+
+ callback = function()
+ if self.navigationMode == NAVIGATION_MODES.CATEGORIES or not self.hasCategories then
+ SCENE_MANAGER:HideCurrentScene()
+ else
+ self:SetNavigationMode(NAVIGATION_MODES.CATEGORIES)
+ end
+ end,
+ },
+
+ --Toggle Queue
+ {
+ alignment = KEYBIND_STRIP_ALIGN_CENTER,
+
+ name = function()
+ local stringId = IsCurrentlySearchingForGroup() and SI_LFG_LEAVE_QUEUE or SI_LFG_JOIN_QUEUE
+ return GetString(stringId)
+ end,
+
+ keybind = "UI_SHORTCUT_SECONDARY",
+
+ callback = function()
+ if IsCurrentlySearchingForGroup() then
+ ZO_Dialogs_ShowGamepadDialog("LFG_LEAVE_QUEUE_CONFIRMATION")
+ else
+ ZO_ACTIVITY_FINDER_ROOT_MANAGER:StartSearch()
+ PlaySound(SOUNDS.DIALOG_ACCEPT)
+ end
+ end,
+
+ visible = function()
+ local anySelected = ZO_ACTIVITY_FINDER_ROOT_MANAGER:IsAnyLocationSelected()
+ local currentlySearching = IsCurrentlySearchingForGroup()
+ local lookingAtEntries = self.entryList:IsActive()
+ local playerCanToggleQueue = IsUnitSoloOrGroupLeader("player")
+ return playerCanToggleQueue and anySelected and (lookingAtEntries or currentlySearching)
+ end,
+ }
+ }
+end
+
+function ZO_ActivityFinderTemplate_Gamepad:FilterByActivity(activityType)
+ self.currentSpecificActivityType = activityType
+ self:RefreshView()
+end
+
+function ZO_ActivityFinderTemplate_Gamepad:PerformUpdate()
+ --Must be overriden
+end
+
+--Add an ethereal entry to interact with the roles
+function ZO_ActivityFinderTemplate_Gamepad:AddRolesMenuEntry(list)
+ local entryData = ZO_GamepadEntryData:New("")
+ entryData.data =
+ {
+ isRoleSelector = true,
+ }
+
+ list:AddEntry("ZO_GamepadMenuEntryTemplate", entryData)
+end
+
+function ZO_ActivityFinderTemplate_Gamepad:RefreshSelections()
+ KEYBIND_STRIP:UpdateKeybindButtonGroup(self.keybindStripDescriptor)
+ self:RefreshView()
+end
+
+function ZO_ActivityFinderTemplate_Gamepad:RefreshHeaderAndView(headerData)
+ self.headerData = headerData
+
+ ZO_GamepadGenericHeader_Refresh(self.header, self.headerData)
+ if self.headerData.tabBarEntries then
+ ZO_GamepadGenericHeader_Activate(self.header)
+ else
+ ZO_GamepadGenericHeader_Deactivate(self.header)
+ end
+ ZO_ACTIVITY_FINDER_ROOT_MANAGER:ClearSelections()
+ self:RefreshView()
+end
+
+function ZO_ActivityFinderTemplate_Gamepad:RefreshView()
+ if not self.scene:IsShowing() or self.navigationMode == NAVIGATION_MODES.CATEGORIES then
+ return
+ end
+
+ self.entryList:Clear()
+ self:AddRolesMenuEntry(self.entryList)
+ local isSearching = IsCurrentlySearchingForGroup()
+
+ if self.navigationMode == NAVIGATION_MODES.RANDOM_ENTRIES then
+ for _, entryData in ipairs(self.randomEntryDatas) do
+ local lockReasonText = self:GetLevelLockTextByActivity(entryData.data.activityType)
+ if not lockReasonText then
+ local reason = ZO_ACTIVITY_FINDER_ROOT_MANAGER:GetLockReasonForActivityType(entryData.data.activityType)
+ if reason then
+ lockReasonText = reason
+ end
+ end
+
+ entryData.data.isLocked = lockReasonText ~= nil
+ entryData.data.lockReasonText = lockReasonText
+
+ entryData:SetEnabled(not entryData.data.isLocked and not isSearching)
+ entryData:SetSelected(ZO_ACTIVITY_FINDER_ROOT_MANAGER:IsActivityTypeSelected(entryData.data.activityType))
+ self.entryList:AddEntry("ZO_GamepadItemSubEntryTemplate", entryData)
+ end
+ else
+ local locationData = ZO_ACTIVITY_FINDER_ROOT_MANAGER:GetLocationsData(self.currentSpecificActivityType)
+ for locationIndex, location in ipairs(locationData) do
+ local specificEntryData = ZO_GamepadEntryData:New(location.nameGamepad, self.categoryData.menuIcon)
+ specificEntryData.data = location
+ specificEntryData:SetEnabled(not location.isLocked and not isSearching)
+ specificEntryData:SetSelected(location.isSelected)
+ self.entryList:AddEntry("ZO_GamepadItemSubEntryTemplate", specificEntryData)
+ end
+ end
+
+ self.entryList:Commit()
+end
+
+function ZO_ActivityFinderTemplate_Gamepad:RefreshSpecificFilters()
+ --Specific header data
+
+ local specificHeaderData
+ local modes = self.dataManager:GetFilterModeData()
+ local modeActivityTypes = modes:GetActivityTypes()
+
+ local validActivityTypes = {}
+ for _, activityType in ipairs(modeActivityTypes) do
+ local isLocked = self:GetLevelLockInfoByActivity(activityType)
+ if not isLocked then
+ local data =
+ {
+ activityType = activityType,
+ name = GetString("SI_LFGACTIVITY", activityType)
+ }
+ table.insert(validActivityTypes, data)
+ end
+ end
+
+ if #validActivityTypes > 1 then
+ local tabBarEntries = {}
+ for _, activityData in ipairs(validActivityTypes) do
+ local tabData =
+ {
+ text = activityData.name,
+ callback = function() self:FilterByActivity(activityData.activityType) end,
+ }
+ table.insert(tabBarEntries, tabData)
+ end
+ specificHeaderData = { tabBarEntries = tabBarEntries }
+ elseif #validActivityTypes == 1 then
+ self.currentSpecificActivityType = validActivityTypes[1].activityType
+ specificHeaderData =
+ {
+ titleText = validActivityTypes[1].name,
+ }
+ end
+
+ self.specificHeaderData = specificHeaderData
+end
+
+function ZO_ActivityFinderTemplate_Gamepad:RefreshFilters()
+ self:RefreshSpecificFilters()
+ if self.navigationMode == NAVIGATION_MODES.SPECIFIC_ENTRIES then
+ self:RefreshHeaderAndView(self.specificHeaderData)
+ end
+end
+
+function ZO_ActivityFinderTemplate_Gamepad:OnGroupingToolsStatusUpdate()
+ KEYBIND_STRIP:UpdateKeybindButtonGroup(self.keybindStripDescriptor)
+ self:RefreshView()
+end
+
+function ZO_ActivityFinderTemplate_Gamepad:OnShowing()
+ local navigationMode = self.hasCategories and NAVIGATION_MODES.CATEGORIES or NAVIGATION_MODES.SPECIFIC_ENTRIES
+ self.isShowingSingularPanel = false
+ self:SetNavigationMode(navigationMode)
+end
+
+function ZO_ActivityFinderTemplate_Gamepad:OnShow()
+ local shouldShowLFMPrompt, lfmPromptActivityName = self:GetLFMPromptInfo()
+ if shouldShowLFMPrompt then
+ ZO_Dialogs_ShowGamepadDialog("PROMPT_FOR_LFM_REQUEST", nil, {mainTextParams = { lfmPromptActivityName }})
+ end
+end
+
+function ZO_ActivityFinderTemplate_Gamepad:SetNavigationMode(navigationMode)
+ --Determine the target list and header
+ local targetList, targetHeader
+ if navigationMode == NAVIGATION_MODES.CATEGORIES then
+ targetList = self.categoryList
+ targetHeader = self.categoryHeaderData
+ else
+ targetList = self.entryList
+ if navigationMode == NAVIGATION_MODES.RANDOM_ENTRIES then
+ targetHeader = self.randomHeaderData
+ else
+ targetHeader = self.specificHeaderData
+ end
+ end
+
+ --Make sure we aren't interacting with the roles bar when we get there
+ local targetData = targetList:GetTargetData()
+ if targetData and targetData.data.isRoleSelector then
+ local DONT_ANIMATE = false
+ local ALLOW_EVEN_IF_DISABLED = true
+ targetList:SetDefaultIndexSelected(DONT_ANIMATE, ALLOW_EVEN_IF_DISABLED)
+ else
+ GAMEPAD_GROUP_ROLES_BAR:Deactivate()
+ end
+
+ --Refresh only if it's not already the current list
+ if self.navigationMode ~= navigationMode then
+ self.navigationMode = navigationMode
+ self:SetCurrentList(targetList)
+ self:RefreshHeaderAndView(targetHeader)
+ end
+
+ self:RefreshSingularSectionPanel()
+end
+
+do
+ local GROUP_SIZE_ICON_FORMAT = zo_iconFormat("EsoUI/Art/LFG/Gamepad/gp_LFG_icon_groupSize.dds", 40, 40)
+
+ function ZO_ActivityFinderTemplate_Gamepad:RefreshSingularSectionPanel()
+ if self.navigationMode ~= NAVIGATION_MODES.CATEGORIES then
+ local currentList = self:GetCurrentList()
+ if currentList then
+ local targetData = currentList:GetTargetData()
+ if targetData then
+ local entryData = targetData.data
+ if not entryData.isRoleSelector then
+ if not self.isShowingSingularPanel then
+ SCENE_MANAGER:AddFragmentGroup(self.singularFragmentGroup)
+ self.isShowingSingularPanel = true
+ end
+
+ self.backgroundTexture:SetTexture(entryData.descriptionTextureGamepad)
+ self.titleLabel:SetText(entryData.nameGamepad)
+ self.descriptionLabel:SetText(entryData.description)
+ ZO_ActivityFinderTemplate_Shared.SetGroupSizeRangeText(self.groupSizeRangeLabel, entryData, GROUP_SIZE_ICON_FORMAT)
+
+ self:RefreshRewards(entryData.isRandom, entryData.activityType)
+ if entryData.isLocked then
+ self.lockControl:SetHidden(false)
+ self.lockReasonLabel:SetText(entryData.lockReasonText)
+ else
+ self.lockControl:SetHidden(true)
+ end
+
+ return
+ end
+ end
+ end
+ end
+
+ if self.isShowingSingularPanel then
+ SCENE_MANAGER:RemoveFragmentGroup(self.singularFragmentGroup)
+ self.isShowingSingularPanel = false
+ end
+ end
+end
+
+function ZO_ActivityFinderTemplate_Gamepad:OnCooldownsUpdate()
+ if self.navigationMode == NAVIGATION_MODES.RANDOM_ENTRIES then
+ local currentList = self:GetCurrentList()
+ if currentList then
+ local targetData = currentList:GetTargetData()
+ if targetData then
+ local entryData = targetData.data
+ if not entryData.isRoleSelector then
+ self:RefreshRewards(entryData.isRandom, entryData.activityType)
+ end
+ end
+ end
+ end
+end
+
+function ZO_ActivityFinderTemplate_Gamepad:GetScene()
+ return self.scene
+end
\ No newline at end of file