You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

427 lines
11 KiB

-------------------------------------------------
-- Controller hints/input handler for ConsolePort
-------------------------------------------------
-- This file manages support for controller input
-- using ConsolePort, providing input handler and
-- displaying on-screen hints.
-------------------------------------------------
-- Initialization
-------------------------------------------------
local NPC, API, _, L = ImmersionFrame, ImmersionAPI, ...
local HANDLE, KEY
do
-- list of functions existing on the HANDLE
local HANDLE_functions = {
'AddHint';
'RemoveHint';
'IsHintFocus';
'SetHintDisabled';
'GetHintForKey';
'ClearHintsForFrame';
}
-- list of local functions that need to exist
local NPC_functions = {
'ToggleHintState';
'SetImmersionFocus';
'ClearImmersionFocus';
'ParseControllerCommand';
}
-- For programming convenience, set all these functions to no-op
-- if ConsolePort isn't loaded, since they won't be doing anything useful.
if (not ConsolePortUIHandle) then
for _, funcID in ipairs(HANDLE_functions) do
NPC[funcID] = nop
end
for _, funcID in ipairs(NPC_functions) do
NPC[funcID] = nop
end
return
else
HANDLE, KEY = ConsolePortUIHandle, ConsolePort:GetData().KEY
-- If any of the HANDLE functions are missing, bail out.
for _, funcID in ipairs(HANDLE_functions) do
if not HANDLE[funcID] then
return
end
end
end
end
-------------------------------------------------
local Inspector = NPC.Inspector
local Titles = NPC.TitleButtons
local controllerInterrupt
-------------------------------------------------
-------------------------------------------------
-- Hint management
-------------------------------------------------
function NPC:AddHint(buttonID, text)
if controllerInterrupt then
return HANDLE:AddHint(KEY[buttonID], text)
end
end
function NPC:RemoveHint(buttonID)
if controllerInterrupt then
return HANDLE:RemoveHint(KEY[buttonID])
end
end
function NPC:SetHintEnabled(buttonID)
if controllerInterrupt then
return HANDLE:SetHintEnabled(KEY[buttonID])
end
end
function NPC:SetHintDisabled(buttonID)
if controllerInterrupt then
return HANDLE:SetHintDisabled(KEY[buttonID])
end
end
function NPC:ToggleHintState(buttonID, enabled)
if controllerInterrupt then
if enabled then
return self:SetHintEnabled(buttonID)
else
return self:SetHintDisabled(buttonID)
end
end
end
function NPC:GetHintForKey(buttonID)
return HANDLE:GetHintForKey(KEY[buttonID])
end
-------------------------------------------------
-- Handle hintbar focus set/release
-------------------------------------------------
function NPC:SetImmersionFocus()
controllerInterrupt = true
if not L('hideui') then
HANDLE:ShowUI()
HANDLE:HideUI(ImmersionFrame, true)
end
return HANDLE:SetHintFocus(ImmersionFrame)
end
function NPC:ClearImmersionFocus()
controllerInterrupt = false
if HANDLE:IsHintFocus(ImmersionFrame) then
HANDLE:HideHintBar()
if not L('hideui') then
HANDLE:ShowUI()
end
end
return HANDLE:ClearHintsForFrame(ImmersionFrame)
end
---------------------------------------------------------
local ControllerInput = { -- return true when propagating
---------------------------------------------------------
[KEY.UP] = function(self)
if self.TitleButtons:IsVisible() then
self.TitleButtons:SetPrevious()
else
return true
end
end;
[KEY.DOWN] = function(self)
if self.TitleButtons:IsVisible() then
self.TitleButtons:SetNext()
else
return true
end
end;
[KEY.LEFT] = function(self)
if self.isInspecting then
self.Inspector:SetPrevious()
else
return true
end
end;
[KEY.RIGHT] = function(self)
if self.isInspecting then
self.Inspector:SetNext()
else
return true
end
end;
[KEY.SQUARE] = function(self)
if self.isInspecting then
local focus = self.Inspector:GetFocus()
if focus and focus.ModifiedClick then
focus:ModifiedClick()
end
else
local text = self.TalkBox.TextFrame.Text
if text:IsSequence() then
if text:GetNumRemaining() <= 1 then
text:RepeatTexts()
else
text:ForceNext()
end
end
end
end;
[KEY.CIRCLE] = function(self)
if self.isInspecting then
self.Inspector:Hide()
elseif self.hasItems then
self:ShowItems()
end
end;
[KEY.CROSS] = function(self)
-- Gossip/multiple quest choices
if self.TitleButtons:GetMaxIndex() > 0 then
self.TitleButtons:ClickFocused()
-- Item inspection
elseif self.isInspecting then
self.Inspector:ClickFocused()
self.Inspector:Hide()
-- Complete quest
elseif self.lastEvent == 'QUEST_COMPLETE' then
-- if multiple items to choose between and none chosen
if self.TalkBox.Elements.itemChoice == 0 and GetNumQuestChoices() > 1 then
self:ShowItems()
else
self.TalkBox.Elements:CompleteQuest()
end
-- Accept quest
elseif ( self.lastEvent == 'QUEST_DETAIL' or self.lastEvent == 'QUEST_ACCEPTED' ) then
self.TalkBox.Elements:AcceptQuest()
-- Progress quest (why are these functions named like this?)
elseif IsQuestCompletable() then
CompleteQuest()
end
end;
[KEY.TRIANGLE] = function(self) API:CloseGossip() API:CloseQuest() end;
[KEY.OPTIONS] = function(self) API:CloseGossip() API:CloseQuest() end;
[KEY.CENTER] = function(self) API:CloseGossip() API:CloseQuest() end;
[KEY.SHARE] = function(self) API:CloseGossip() API:CloseQuest() end;
-------------------------------------------------
} -----------------------------------------------
-------------------------------------------------
-- HACK: count popups for gossip edge case.
local popupCounter = 0
do
local function PopupFixOnShow() popupCounter = popupCounter + 1 end
local function PopupFixOnHide() popupCounter = popupCounter - 1 end
for i=1, 4 do
_G['StaticPopup'..i]:HookScript('OnShow', PopupFixOnShow)
_G['StaticPopup'..i]:HookScript('OnHide', PopupFixOnHide)
end
end
local function GetUIControlKey(button)
if ConsolePort.GetUIControlKey then
return ConsolePort:GetUIControlKey(GetBindingAction(button))
elseif ConsolePortUIHandle.GetUIControlBinding then
return ConsolePortUIHandle:GetUIControlBinding(button)
end
end
function NPC:ParseControllerCommand(button)
if controllerInterrupt then
-- Handle edge case when CP cursor should precede Immersion input.
if not ConsolePort:GetData()('disableUI') then
if ( popupCounter > 0 ) or ( AzeriteEmpoweredItemUI and AzeriteEmpoweredItemUI:IsVisible() ) then
return false
end
end
-- Handle case when the inspect binding or M1 is pressed,
-- in which case it should show the item inspector.
if self:IsInspectModifier(button) or button:match('SHIFT') then
self.Inspector:ShowFocusedTooltip(true)
return true
end
-- Handle every other case of possible controller inputs.
local keyID = GetUIControlKey(button)
local func = keyID and ControllerInput[keyID]
if func then
return not func(self)
end
end
end
----------------------------------
-- Button selector
----------------------------------
local Selector = {}
function Selector:SetFocus(index)
if index then --self:IsVisible() and index then
local focus = self:GetFocus()
if focus then
focus:UnlockHighlight()
focus:OnLeave()
end
local max = self:GetMaxIndex()
self.index = ( index > max and max ) or ( index < 1 and 1 ) or index
self:SetFocusHighlight()
if max > 0 and self.HintText then
NPC:AddHint('CROSS', self.HintText)
else
NPC:RemoveHint('CROSS')
end
end
end
function Selector:SetNext()
local nextButton = self:GetNextButton(self.index, 1)
self:SetFocus(nextButton and (nextButton.idx or nextButton:GetID()))
end
function Selector:SetPrevious()
local prevButton = self:GetNextButton(self.index, -1)
self:SetFocus(prevButton and (prevButton.idx or prevButton:GetID()))
end
function Selector:ClickFocused()
local focus = self:GetFocus()
if focus then
focus:Click()
end
end
function Selector:SetFocusHighlight()
local focus = self:GetFocus()
if focus then
focus:LockHighlight()
focus:OnEnter()
end
end
function Selector:GetFocus()
return self.Active[self.index]
end
function Selector:GetActive()
return pairs(self.Active)
end
function Selector:GetNextButton(index, delta)
if index then
local modifier = delta
while true do
local key = index + delta
if key < 1 or key > self:GetMaxIndex() then
return self.Active[self.index]
end
if self.Active[key] then
return self.Active[key]
else
delta = delta + modifier
end
end
end
end
function Selector:GetMaxIndex()
local maxIndex = 0
if self:IsShown() then
for i, button in pairs(self.Active) do
maxIndex = i > maxIndex and i or maxIndex
end
end
return maxIndex
end
function Selector:OnHide()
end
L.Mixin(Inspector, Selector)
L.Mixin(Titles, Selector)
----------------------------------
-- Extended script handlers
----------------------------------
-- Inspector
Inspector.Buttons = {}
Inspector.ignoreModifier = true
Inspector:HookScript('OnShow', function(self)
local parent = self.parent
self.CROSS = select(2, parent:GetHintForKey('CROSS'))
self.CIRCLE = select(2, parent:GetHintForKey('CIRCLE'))
self.SQUARE = select(2, parent:GetHintForKey('SQUARE'))
parent.isInspecting = true
parent:RemoveHint('SQUARE')
parent:AddHint('CIRCLE', CLOSE)
if ( parent.lastEvent == 'QUEST_PROGRESS' ) then
parent:RemoveHint('CROSS')
else
parent:AddHint('CROSS', CHOOSE)
HANDLE:AddHint('M1', CURRENTLY_EQUIPPED)
end
end)
Inspector:HookScript('OnHide', function(self)
local parent = self.parent
parent.isInspecting = false
HANDLE:RemoveHint('M1')
if self.CROSS then
parent:AddHint('CROSS', self.CROSS)
end
if self.SQUARE then
parent:AddHint('SQUARE', self.SQUARE)
end
if self.CIRCLE then
parent:AddHint('CIRCLE', self.CIRCLE)
end
self.CROSS = nil
self.SQUARE = nil
self.CIRCLE = nil
end)
function Inspector:ShowFocusedTooltip(showTooltip)
local button = self:GetFocus()
if button then
if showTooltip then
button:SetFocus()
else
button:ClearFocus()
end
end
end
-- Handle custom modified clicks on item popups:
-- Return itemLink and display text for SQUARE (modified clicks)
local function GetModifiedClickInfo(item)
local link = item and GetQuestItemLink(item.type, item:GetID())
if link and ImmersionAPI:IsAzeriteItem(link) then
----------------------------------------
return link, LFG_LIST_DETAILS
end
end
function L.TooltipMixin:ModifiedClick(...)
local azeriteItemLink = GetModifiedClickInfo(self.item)
if azeriteItemLink then
----------------------------------------
OpenAzeriteEmpoweredItemUIFromLink(azeriteItemLink)
self.inspector:Hide()
end
end
hooksecurefunc(L.TooltipMixin, 'OnEnter', function(self)
local _, hintText = GetModifiedClickInfo(self.item)
if hintText then
Inspector.parent:AddHint('SQUARE', hintText)
end
end)
hooksecurefunc(L.TooltipMixin, 'OnLeave', function(self)
Inspector.parent:RemoveHint('SQUARE')
end)
-- Titles
Titles.HintText = ACCEPT