2 Star 0 Fork 0

mirrors_kylepixel/wow-ui-source

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
securehoverdriver.lua 10.03 KB
一键复制 编辑 原始数据 按行查看 历史
dubcat 提交于 6年前 . 8.1.5.29981
-- SecureHoverDriver.lua -- A driver for automatically hiding frames after
-- a delay
-- Code to manage 'rect sets', these are arrays made up of
-- STATE -- Current visibility management state:
-- "new" - freshly registered
-- false - cursor has yet to enter
-- true - cursor is over
-- <numeric> - remaining seconds before hide
-- TTL -- The TTL to use when the mouse leaves the frame
-- COUNT -- the number of rects in the set
-- BOUNDING BOX (L,R,B,T) -- The bounding box of the set's rects
-- FRAME RECT (L,R,B,T) -- The rect of the 'main' frame
-- 0 or more other rects -- Any other rects that make up the set
--
-- The cursor is in the rect set if it's over the frame rect or any of the
-- other rects. (The bounding box is just an optimization to speed that
-- determination without checking each rect)
local STATE_INDEX = 1;
local TTL_INDEX = 2;
local COUNT_INDEX = 3;
local BOUNDING_INDEX = 4;
local FRAME_INDEX = BOUNDING_INDEX + 4;
-- Create a new set, possibly re-using an existing array
local function RectSet_Create(l, r, b, t, TTL, S)
if (S) then
S[1] = "new";
S[2] = tonumber(TTL) or 0; -- ttl
S[3] = 1; -- count
S[4] = l; S[5] = r; S[6] = b; S[7] = t;
S[8] = l; S[9] = r; S[10] = b; S[11] = t;
else
S = { "new", tonumber(TTL) or 0, 1, l, r, b, t, l, r, b, t }
end
return S;
end
-- Add a new rect to a set, attempting to minimize growth of the set
-- (without getting too carried away)
local function RectSet_Add(S, NL, NR, NB, NT)
local N = S[COUNT_INDEX];
local SL, SR, SB, ST = S[4], S[5], S[6], S[7];
-- First grow the bounding box
if (NL < SL) then S[4] = NL; end
if (NR > SR) then S[5] = NR; end
if (NB < SB) then S[6] = NB; end
if (NT > ST) then S[7] = NT; end
-- Now compare the new rect against the other rects to see
-- if it's wholly contained by, or wholly contains, them.
local MAXIDX = (N - 1) * 4 + FRAME_INDEX;
for i = FRAME_INDEX, MAXIDX, 4 do
SL, SR, SB, ST = S[i], S[i+1], S[i+2], S[i+3];
if ((NL >= SL) and (NR <= SR) and (NB >= SB) and (NT <= ST)) then
-- Wholly contained, dont need to add.
return;
end
if ((NL <= SL) and (NR >= SR) and (NB <= SB) and (NT >= ST)) then
-- Wholly contains existing, replace unless it's the first
if (i > 7) then
S[i], S[i+1], S[i+2], S[i+3] = NL, NR, NB, NT;
return;
end
end
end
-- Finally if we didn't find a match, add this one to the end
S[COUNT_INDEX] = N + 1;
local i = MAXIDX + 4;
S[i], S[i+1], S[i+2], S[i+3] = NL, NR, NB, NT;
end
-- Check if a set of coordinates is over the rect set
local function RectSet_IsOver(S, X, Y)
local N = S[COUNT_INDEX];
local MAXIDX = N * 4 + BOUNDING_INDEX;
for i = BOUNDING_INDEX, MAXIDX, 4 do
local R = (X >= S[i]) and (X <= S[i+1]) and
(Y >= S[i+2]) and (Y <= S[i+3]);
if (R) then
if (i > BOUNDING_INDEX) then return true, ((i - 3) / 4); end
else
if (i == BOUNDING_INDEX) then return false, "bound"; end
end
end
return false, "nomatch";
end
-- Utility method to get a screen-normalized rect for a frame
local function GetScreenFrameRect(frame)
local es = frame:GetEffectiveScale();
local l, b, w, h = frame:GetRect();
if (not (l and b)) then return 0, 0, 0, 0; end
return l * es, (l + w) * es, b * es, (b + h) * es;
end
---------------------------------------------------------------------------
-- Actual tracking and registration code
local LOCAL_TrackedHovers = {};
local LOCAL_PendingHides = {};
local LOCAL_AnyPendingHides = false;
local function UpdateTrackedHovers(self, elapsed)
local cursorX, cursorY = GetCursorPosition();
for frame, rectSet in pairs(LOCAL_TrackedHovers) do
if (not frame:IsVisible()) then
-- Discard if hidden
LOCAL_TrackedHovers[frame] = nil;
end
local cur = rectSet[STATE_INDEX];
local state = RectSet_IsOver(rectSet, cursorX, cursorY);
if (state) then
rectSet[STATE_INDEX] = true;
else
if (cur == true) then
-- The mouse has just left the rect set, check if the
-- parent frame is still in the same place, and if so
-- grab the TTL
local FL, FR, FB, FT = GetScreenFrameRect(frame);
if ((FL == rectSet[8]) and (FR == rectSet[9])
and (FB == rectSet[10]) and (FT == rectSet[11])) then
cur = rectSet[TTL_INDEX];
else
-- frame moved, discard
cur = nil;
LOCAL_TrackedHovers[frame] = nil;
end
elseif (cur == "new") then
-- This is the first update for this frame, and the cursor
-- isn't yet in it
cur = false;
rectSet[STATE_INDEX] = false;
elseif (cur) then
-- We're already counting down, so subtract the current time
cur = cur - elapsed;
end
-- If we've got something other than nil or false, it's a
-- countdown, so see if it's expired or not
if (cur) then
if (cur > 0) then
-- Still going, save remaining time
rectSet[STATE_INDEX] = cur;
else
-- Expired, discard hover and queue for hide
LOCAL_TrackedHovers[frame] = nil;
LOCAL_PendingHides[frame] = true;
LOCAL_AnyPendingHides = true;
end
end
end
end
if (LOCAL_AnyPendingHides) then
for frame, _ in pairs(LOCAL_PendingHides) do
LOCAL_PendingHides[frame] = nil
frame:Hide();
frame:SetAttribute("statehidden", true);
end
LOCAL_AnyPendingHides = false;
end
if (not next(LOCAL_TrackedHovers)) then
self:Hide();
end
end
-- TODO do I need to make this frame secure? Probably.
local LOCAL_UpdateFrame = CreateFrame("Frame", "SecureHoverDriverManager", nil, "SecureFrameTemplate");
LOCAL_UpdateFrame:SetScript("OnUpdate", UpdateTrackedHovers);
LOCAL_UpdateFrame:Hide();
-- Register a frame for auto-hiding
--
-- frame - the frame to register
-- ttl - the time (in seconds) after leaving the frame before hiding
local function SecureRegisterAutoHide(frame, ttl)
-- TODO check that frame really is a frame?
local l, r, b, t = GetScreenFrameRect(frame);
local rectSet = RectSet_Create(l, r, b, t, ttl, LOCAL_TrackedHovers[frame]);
LOCAL_TrackedHovers[frame] = rectSet;
LOCAL_UpdateFrame:Show();
end
-- Add another frame as a 'child' of the frame to include it in the frame's
-- rectset. This must be called immediately after the initial registration
-- (i.e. before OnUpdate)
--
-- frame - the already registered frame
-- child - the child frame to include in the rect set
local function SecureAddToAutoHide(frame, child)
local rectSet = LOCAL_TrackedHovers[frame];
if (not rectSet) then
error("Parent frame is not registered for auto-hide");
return;
end
if (rectSet[STATE_INDEX] ~= "new") then
error("Parent frame is not freshly registered");
return;
end
-- TODO check that child really is a frame?
local l, r, b, t = GetScreenFrameRect(child);
RectSet_Add(rectSet, l, r, b, t);
end
-- Cancel a frame's auto-hide registration
--
-- frame - the frame to unregister
local function SecureUnregisterAutoHide(frame)
LOCAL_TrackedHovers[frame] = nil;
end
local function SecureHoverDriverManager_OnAttributeChanged(self, name, value)
if ( not value ) then
return;
end
if ( name == "setframe" ) then
return;
elseif ( name == "unregister" ) then
local frame = value;
if (frame) then
SecureUnregisterAutoHide(frame);
end
elseif ( name == "register" ) then
local duration = tonumber(value);
if (not duration) then
return;
end
if (duration < 0) then
duration = 0;
end
local frame = self:GetAttribute("setframe");
if (frame) then
SecureRegisterAutoHide(frame, duration);
end
elseif ( name == "add" ) then
local child = value;
local frame = self:GetAttribute("setframe");
if (frame and child) then
SecureAddToAutoHide(frame, child);
end
end
end
LOCAL_UpdateFrame:SetScript("OnAttributeChanged", SecureHoverDriverManager_OnAttributeChanged);
-- Register a frame for auto-hiding
--
-- frame - the frame to register
-- ttl - the time (in seconds) after leaving the frame before hiding
function RegisterAutoHide(frame, ttl)
if (issecure()) then
return SecureRegisterAutoHide(frame, tonumber(ttl));
end
LOCAL_UpdateFrame:SetAttribute("setframe", frame);
LOCAL_UpdateFrame:SetAttribute("register", tonumber(ttl));
end
-- Add another frame as a 'child' of the frame to include it in the frame's
-- rectset. This must be called immediately after the initial registration
-- (i.e. before OnUpdate)
--
-- frame - the already registered frame
-- child - the child frame to include in the rect set
function AddToAutoHide(frame, child)
if (issecure()) then
return SecureAddToAutoHide(frame, child);
end
local rectSet = LOCAL_TrackedHovers[frame];
if (not rectSet) then
error("Parent frame is not registered for auto-hide");
return;
end
if (rectSet[STATE_INDEX] ~= "new") then
error("Parent frame is not freshly registered");
return;
end
LOCAL_UpdateFrame:SetAttribute("setframe", frame);
LOCAL_UpdateFrame:SetAttribute("add", child);
end
-- Cancel a frame's auto-hide registration
--
-- frame - the frame to unregister
function UnregisterAutoHide(frame)
if (issecure()) then
return SecureUnregisterAutoHide(frame);
end
LOCAL_UpdateFrame:SetAttribute("unregister", frame);
end
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/mirrors_kylepixel/wow-ui-source.git
git@gitee.com:mirrors_kylepixel/wow-ui-source.git
mirrors_kylepixel
wow-ui-source
wow-ui-source
master

搜索帮助