--[[ Grid Selector Code ]]-- -- The user should call ZO_GamepadGrid:Activate() and ZO_GamepadGrid:Deactivate() as appropriate ZO_GamepadGrid = ZO_InitializingCallbackObject:Subclass() -- rowMajor = true specifies that you have a grid of rows with a potentially variable number of columns in each row -- rowMajor = false specifies that you have a grid of columns with a potentially variable number of rows in each column function ZO_GamepadGrid:Initialize(control, rowMajor) self.control = control self.focusX = 1 self.focusY = 1 self.rowMajor = rowMajor self.active = false self.verticalMovementController = ZO_MovementController:New(MOVEMENT_CONTROLLER_DIRECTION_VERTICAL) self.horizontalMovementController = ZO_MovementController:New(MOVEMENT_CONTROLLER_DIRECTION_HORIZONTAL) self.directionalMovementSound = SOUNDS.HOR_LIST_ITEM_SELECTED SCREEN_NARRATION_MANAGER:RegisterGamepadGrid(self) end function ZO_GamepadGrid:GetIsRowMajor() return self.rowMajor end function ZO_GamepadGrid:GetGridItems() -- This should be overridden to return an list of lists of grid controls end function ZO_GamepadGrid:RefreshGridHighlight() -- This should be overridden to refresh the grid highlight (when focus changes) end function ZO_GamepadGrid:ClampToGrid(x,y) local items = self:GetGridItems() if #items > 0 then if self.rowMajor then y = zo_clamp(y, 1, #items) x = zo_clamp(x, 1, #items[y]) else x = zo_clamp(x, 1, #items) y = zo_clamp(y, 1, #items[x]) end else x = 0 y = 0 end return x,y end function ZO_GamepadGrid:GetGridPosition() -- Clamp them again to make sure they are valid (just in case the grid changes) self.focusX, self.focusY = self:ClampToGrid(self.focusX, self.focusY) return self.focusX, self.focusY end function ZO_GamepadGrid:ResetGridPosition() self.focusX = 1 self.focusY = 1 self:RefreshGridHighlight() end function ZO_GamepadGrid:UpdateDirectionalInput() local x = self.focusX local y = self.focusY local move = self.verticalMovementController:CheckMovement() if move == MOVEMENT_CONTROLLER_MOVE_NEXT then y = y + 1 elseif move == MOVEMENT_CONTROLLER_MOVE_PREVIOUS then y = y - 1 end local move = self.horizontalMovementController:CheckMovement() if move == MOVEMENT_CONTROLLER_MOVE_NEXT then x = x + 1 elseif move == MOVEMENT_CONTROLLER_MOVE_PREVIOUS then x = x - 1 end x, y = self:ClampToGrid(x, y) if (self.focusX ~= x or self.focusY ~= y) then self.focusX = x self.focusY = y PlaySound(self.directionalMovementSound) self:RefreshGridHighlight() self:FireCallbacks("FocusChanged") end end function ZO_GamepadGrid:SetDirectionalMovementSound(sound) self.directionalMovementSound = sound end function ZO_GamepadGrid:IsActive() return self.active end function ZO_GamepadGrid:Activate() KEYBIND_STRIP:AddKeybindButtonGroup(self.keybindStripDescriptor) DIRECTIONAL_INPUT:Activate(self, self.control) self.active = true self:FireCallbacks("OnActivated") end function ZO_GamepadGrid:Deactivate() DIRECTIONAL_INPUT:Deactivate(self) KEYBIND_STRIP:RemoveKeybindButtonGroup(self.keybindStripDescriptor) self.active = false end function ZO_GamepadGrid:GetNarrationText() --This should be overridden to get the narration text (if there is any) end function ZO_GamepadGrid:GetHeaderNarration() --This should be overridden to get the header narration text (if there is any) end -- -- ZO_GamepadPagedGrid -- ZO_GamepadPagedGrid = ZO_GamepadGrid:Subclass() function ZO_GamepadPagedGrid:Initialize(control, rowMajor, footerControl) ZO_GamepadGrid.Initialize(self, control, rowMajor) self:SetDirectionalMovementSound(SOUNDS.GAMEPAD_MENU_UP) if footerControl then self.footer = { control = footerControl, previousControl = footerControl:GetNamedChild("PreviousButton"), nextControl = footerControl:GetNamedChild("NextButton"), pageNumberLabel = footerControl:GetNamedChild("PageNumberText"), } end self.currentPage = 0 self.numPages = 0 self:InitializeKeybindStripDescriptors() end function ZO_GamepadPagedGrid:SetPageNumberFont(font) if self.footer then self.footer.pageNumberLabel:SetFont(font) end end function ZO_GamepadPagedGrid:SetPageInfo(currentPage, numPages) self.currentPage = currentPage self.numPages = numPages if self.currentPage > self.numPages then self.currentPage = self.numPages end self:UpdateForPageChange() end function ZO_GamepadPagedGrid:UpdateForPageChange() if self.footer then local enablePrevious = self.currentPage ~= 1 local enableNext = self.currentPage ~= self.numPages local hideButtons = not (enablePrevious or enableNext) local nextControl = self.footer.nextControl local prevControl = self.footer.previousControl local pageLabel = self.footer.pageNumberLabel nextControl:SetHidden(hideButtons) prevControl:SetHidden(hideButtons) nextControl:SetEnabled(enableNext) prevControl:SetEnabled(enablePrevious) pageLabel:SetHidden(hideButtons) if not hideButtons then pageLabel:SetText(zo_strformat(SI_GAMEPAD_PAGED_LIST_PAGE_NUMBER, self.currentPage)) end end self:RefreshGrid() if self.pageChangedCallback then self.pageChangedCallback() end KEYBIND_STRIP:UpdateKeybindButtonGroup(self.keybindStripDescriptor) end function ZO_GamepadPagedGrid:SetPageChangedCallback(callback) self.pageChangedCallback = callback end function ZO_GamepadPagedGrid:GetCurrentPage() return self.currentPage end function ZO_GamepadPagedGrid:GetCurrentPageNarration() return SCREEN_NARRATION_MANAGER:CreateNarratableObject(zo_strformat(SI_GAMEPAD_PAGED_LIST_PAGE_NUMBER_NARRATION, self.currentPage)) end function ZO_GamepadPagedGrid:GetNumPages() return self.numPages end function ZO_GamepadPagedGrid:NextPage() if self.currentPage < self.numPages then self.currentPage = self.currentPage + 1 self:UpdateForPageChange() PlaySound(SOUNDS.GAMEPAD_PAGE_FORWARD) local NARRATE_HEADER = true SCREEN_NARRATION_MANAGER:QueueGamepadGridEntry(self, NARRATE_HEADER) end end function ZO_GamepadPagedGrid:PreviousPage() if self.currentPage > 1 then self.currentPage = self.currentPage - 1 self:UpdateForPageChange() PlaySound(SOUNDS.GAMEPAD_PAGE_BACK) local NARRATE_HEADER = true SCREEN_NARRATION_MANAGER:QueueGamepadGridEntry(self, NARRATE_HEADER) end end function ZO_GamepadPagedGrid:InitializeKeybindStripDescriptors() local function ShouldNarrateKeybinds() return self.currentPage ~= 1 or self.currentPage ~= self.numPages end self.keybindStripDescriptor = { alignment = KEYBIND_STRIP_ALIGN_LEFT, { --Even though this is an ethereal keybind, the name will still be read during screen narration name = GetString(SI_GAMEPAD_PAGED_LIST_PAGE_LEFT_NARRATION), keybind = "UI_SHORTCUT_LEFT_TRIGGER", ethereal = true, narrateEthereal = ShouldNarrateKeybinds, etherealNarrationOrder = 1, callback = function() self:PreviousPage() end, enabled = function() return self.currentPage > 1 end, }, { --Even though this is an ethereal keybind, the name will still be read during screen narration name = GetString(SI_GAMEPAD_PAGED_LIST_PAGE_RIGHT_NARRATION), keybind = "UI_SHORTCUT_RIGHT_TRIGGER", ethereal = true, narrateEthereal = ShouldNarrateKeybinds, etherealNarrationOrder = 2, callback = function() self:NextPage() end, enabled = function() return self.currentPage < self.numPages end, }, } end function ZO_GamepadPagedGrid:RefreshGrid() -- This should be overridden and will be called when a page change occurs end