ZO_MouseInputGroup = ZO_Object:Subclass() ZO_MOUSE_INPUT_GROUP_MOUSE_OVER = "mouseOver" function ZO_MouseInputGroup:New(...) local object = ZO_Object.New(self) object:Initialize(...) return object end function ZO_MouseInputGroup:Initialize(rootControl) self.over = false self.inputTypeGroups = { } self.rootControl = rootControl self.refreshMouseOverFunction = function() self:RefreshMouseOver() end self.rootMouseEnterFunction = rootControl:GetHandler("OnMouseEnter") self.rootMouseExitFunction = rootControl:GetHandler("OnMouseExit") rootControl:SetHandler("OnMouseEnter", nil) rootControl:SetHandler("OnMouseExit", nil) self:Add(rootControl, ZO_MOUSE_INPUT_GROUP_MOUSE_OVER) end function ZO_MouseInputGroup:GetInputTypeGroup(inputType) local inputTypeGroup = self.inputTypeGroups[inputType] if not inputTypeGroup then inputTypeGroup = {} self.inputTypeGroups[inputType] = inputTypeGroup end return inputTypeGroup end function ZO_MouseInputGroup:Contains(control, inputType) if control:IsMouseEnabled() then local groupControls = self:GetInputTypeGroup(inputType) for _, groupControl in pairs(groupControls) do if control == groupControl then return true end end end return false end function ZO_MouseInputGroup:Add(control, inputType) if control:IsMouseEnabled() then local groupControls = self:GetInputTypeGroup(inputType) table.insert(groupControls, control) if inputType == ZO_MOUSE_INPUT_GROUP_MOUSE_OVER then control:SetHandler("OnMouseEnter", self.refreshMouseOverFunction, inputType, CONTROL_HANDLER_ORDER_BEFORE) control:SetHandler("OnMouseExit", self.refreshMouseOverFunction, inputType, CONTROL_HANDLER_ORDER_BEFORE) end end end function ZO_MouseInputGroup:AddControlAndAllChildren(control, inputType) self:Add(control, inputType) for i = 1, control:GetNumChildren() do self:AddControlAndAllChildren(control:GetChild(i), inputType) end end function ZO_MouseInputGroup:RemoveAll(inputType, excludedControls) -- Optional exclusion of a single control, or a numerically indexed table -- of controls, from this remove operation. if excludedControls and type(excludedControls) ~= "table" then excludedControls = {excludedControls} end local groupControls = self:GetInputTypeGroup(inputType) for controlIndex = #groupControls, 1, -1 do local control = groupControls[controlIndex] -- Remove all controls in the group except the root control. if control ~= self.rootControl then if not excludedControls or not ZO_IsElementInNumericallyIndexedTable(excludedControls, control) then table.remove(groupControls, controlIndex) control:SetHandler("OnMouseEnter", nil, inputType) control:SetHandler("OnMouseExit", nil, inputType) end end end end function ZO_MouseInputGroup:IsControlInGroup(searchControl, inputType) local groupControls = self:GetInputTypeGroup(inputType) for _, control in ipairs(groupControls) do if searchControl == control then return true end end return false end function ZO_MouseInputGroup:RefreshMouseOver() local currentMouseOverControlInGroup = false --there seems to be a weird case where 3D controls can be mouse entered when exiting UI mode. So we prevent this from registering enters when not in UI mode if SCENE_MANAGER:IsInUIMode() then currentMouseOverControlInGroup = self:IsControlInGroup(WINDOW_MANAGER:GetMouseOverControl(), ZO_MOUSE_INPUT_GROUP_MOUSE_OVER) end if currentMouseOverControlInGroup ~= self.over then self.over = currentMouseOverControlInGroup if self.over then self.rootMouseEnterFunction(self.rootControl) else self.rootMouseExitFunction(self.rootControl) end end end --XML Handlers function ZO_MouseOverGroupFromChildren_OnInitialized(self) local group = ZO_MouseInputGroup:New(self) group:AddControlAndAllChildren(self, ZO_MOUSE_INPUT_GROUP_MOUSE_OVER) end