- Joined
- Jul 18, 2010
- Messages
- 2,377
This is a Lua resource that allows to make Frames moveable by the user using drag and drop. The user right clicks a frame and while he holds the right mouse button the frame will follow the mouse. Only frames supporting a Frame Mouse Enter event can be made move able with this resource.
It uses a modified version of global init from Bribe.
How this get the mouse screen position when there is not GetMouseScreenPos?
It creates a grid of invisible Frames each knowing its own position each such frame has a tooltip if that tooltip is visible the mouse is on its position. This requires an huge amount of frames ~10k.
This grid is the system FrameGrid.
The moveable System is this one:
It uses a modified version of global init from Bribe.
How this get the mouse screen position when there is not GetMouseScreenPos?
It creates a grid of invisible Frames each knowing its own position each such frame has a tooltip if that tooltip is visible the mouse is on its position. This requires an huge amount of frames ~10k.
This grid is the system FrameGrid.
Lua:
--[[FrameGrid by Tasyen
--Got that Idea from CanFight, he mentioned something about a FPS game in which he clustered the screen with Frames to know the mouse position.
function FrameGrid.show(flag, player)
show/hide the grid for player nil or GetLocalPlayer affect all players
--]]
FrameGrid = {}
FrameGrid.Boss = nil --the parent hide/show it to enable/disable the functionality of this system.
FrameGrid.GridFrames = {} --all grid frames
FrameGrid.GridFrames2 = {} --the tooltip frames of the grid
FrameGrid.LastFrame = 0 --the index of the frame hovered by the mouse, might be incorrect sometimes
onGameStart(function()
-- print("FrameGrid.Init")
FrameGrid.Timer = CreateTimer()
TimerStart(FrameGrid.Timer, 0.01, true, FrameGrid.update)
--the Grid Boss Frame its a BUTTON so it can have a higher Frame Level.
--This Frame is used as on/off, when showing it the FrameGrid becomes active while it does nothing when Boss is disabled.
FrameGrid.Boss = BlzCreateFrameByType("BUTTON", "FrameGridBoss", BlzGetOriginFrame(ORIGIN_FRAME_GAME_UI, 0),"",0)
--be above other frames, using this allows to move into other frames but also stops their mouse enter events while FrameGrid is active.
--I wasn't able to change this value at a later time hence there is no swap for this.
--BlzFrameSetLevel(FrameGrid.Boss, 7)
local xSize = 0.01 --dont go to low
local ySize = 0.01 --dont go to low
local yStart = ySize/2
local xStart = xSize/2
FrameGrid.FramesEachCol = 0.6 / ySize
for x = xStart, 0.8, xSize do
for y = yStart, 0.6, ySize do
local newButton = BlzCreateFrameByType("FRAME", "", FrameGrid.Boss,"",0)
local tooltipButton = BlzCreateFrameByType("FRAME", "", FrameGrid.Boss,"",0)
BlzFrameSetAbsPoint(newButton, FRAMEPOINT_CENTER, x, y)
BlzFrameSetSize(newButton, xSize, ySize)
BlzFrameSetTooltip(newButton, tooltipButton)
BlzFrameSetEnable(newButton, false)
BlzFrameSetEnable(tooltipButton, false)
FrameGrid[newButton] = {x, y}
FrameGrid[tooltipButton] = {x, y}
table.insert(FrameGrid.GridFrames, newButton)
table.insert(FrameGrid.GridFrames2, tooltipButton)
end
end
BlzFrameSetVisible(FrameGrid.Boss, false)
end)
function FrameGrid.updateSimple()
--Grid visible?
if BlzFrameIsVisible(FrameGrid.Boss) then
--loop all Tooltip Frames and find the visible one. The visible one is the position of the mouse on the screen.
--this is a bit inefficent in worst case one iterates 4800 times, frames are saved in col wise means as farer left the mouse is as faster this is done.
--when beeing at left it only takes no os.clock time while it takes ~ 0.003 or 0.005 seconds on the right
--local count = 0
--local time = os.clock()
for index, value in ipairs(FrameGrid.GridFrames2)
do
--count = count + 1
if BlzFrameIsVisible(value) then
-- FrameGrid.LastY = FrameGrid[value][2]
MoveAbleFrame.moveFrame(FrameGrid[value][1], FrameGrid[value][2])
break
end
end
--print(count)
--print("count:",count, "os.clock", os.clock() - time)
-- print(os.clock() - time)
end
end
function FrameGrid.update()
--Grid visible?
if BlzFrameIsVisible(FrameGrid.Boss) then
--search the visible Tooltip Frame in both directions from the last found position.
--this way speeds it up when doing only small steps, average was for me 60 to 240 steps and resulting into 0 or sometimes ~0.0009 ~0.001 os.clock dif
--local count = 0
--local time = os.clock()
local yA = FrameGrid.LastFrame
local yB = FrameGrid.LastFrame
while (yA > 0 or yB < 4800)
do
--count = count + 1
if yA >= 0 then
if BlzFrameIsVisible(FrameGrid.GridFrames2[yA]) then
FrameGrid.LastFrame = yA
MoveAbleFrame.moveFrame(FrameGrid[FrameGrid.GridFrames2[yA]][1], FrameGrid[FrameGrid.GridFrames2[yA]][2])
break
end
yA = yA - 1
end
if BlzFrameIsVisible(FrameGrid.GridFrames2[yB]) then
FrameGrid.LastFrame = yB
MoveAbleFrame.moveFrame(FrameGrid[FrameGrid.GridFrames2[yB]][1], FrameGrid[FrameGrid.GridFrames2[yB]][2])
break
else
yB = yB + 1
end
end
--print("count:",count, "os.clock", os.clock() - time)
--print(os.clock() - time)
end
end
function FrameGrid.show(flag, player)
if not player or GetLocalPlayer() == player then
BlzFrameSetVisible(FrameGrid.Boss, flag)
end
end
The moveable System is this one:
Lua:
--[[
MoveAbleFrame (Mini) by Tasyen
MoveAbleFrame allows to drag&drop frames you have setuped to be moveable. This System is async do not use anthing of it in a sync manner. (Mini) does not save frame positions
function MoveAbleFrame.setup(frame)
makes this frame moveable by user with drag and drop, only works on frameTypes supporting FRAMEEVENT_MOUSE_ENTER and FRAMEEVENT_MOUSE_LEAVE
has to be called sync cause it creates events, unlike the other userMoveAbleFrame functions which should be used async
The user changed position can be saved in a file and loaded. The frames are identyfied by the order, they were added to userMoveAbleFrame.
Means when adding new userMoveAbleFrames not to the end (order wise), then a saved File can move a wrong frame when loading an File saved with an old version.
function MoveAbleFrame.enable(player[, flag])
(dis)allows drag and drop moveable Frames for player, use GetLocalPlayer() to affect all players
can be called without flag in such a case the current value is negated. true <-> false
this has no impact on current done drag&dropping
returns the value of MoveAbleFrame.Enabled
--]]
MoveAbleFrame = {}
MoveAbleFrame.Enabled = false --only when this is true, right clicking will have an effect on frames
MoveAbleFrame.Frame = nil -- the Frame beeing Moved
MoveAbleFrame.FramePoint = nil -- the FramePoint Frame is posed with nil = CENTER
function MoveAbleFrame.startMoving(frame, framePoint)
MoveAbleFrame.Frame = frame
if not framePoint then
framePoint = FRAMEPOINT_CENTER
end
MoveAbleFrame.FramePoint = framePoint
FrameGrid.show(true)
end
function MoveAbleFrame.moveFrame(x, y, finish)
BlzFrameClearAllPoints(MoveAbleFrame.Frame)
BlzFrameSetAbsPoint(MoveAbleFrame.Frame, MoveAbleFrame.FramePoint, x, y)
if finish then
FrameGrid.show(false)
end
end
function MoveAbleFrame.enable(player, flag)
if GetLocalPlayer() == player then
if flag == nil then
MoveAbleFrame.Enabled = not MoveAbleFrame.Enabled
else
MoveAbleFrame.Enabled = flag
end
end
return MoveAbleFrame.Enabled
end
function MoveAbleFrame.setup(frame)
if not MoveAbleFrame[frame] then
MoveAbleFrame[frame] = true
BlzTriggerRegisterFrameEvent(MoveAbleFrame.TriggerFrameEnter, frame, FRAMEEVENT_MOUSE_ENTER) --enable the hover feature
BlzTriggerRegisterFrameEvent(MoveAbleFrame.TriggerFrameLeave , frame, FRAMEEVENT_MOUSE_LEAVE)
end
end
onTriggerInit(function()
xpcall(function()
-- print("MoveAbleFrame.Init")
--this is the FrameEnter Event trigger, every moveable Frame calls it, when entering remember the entere Frame
MoveAbleFrame.TriggerFrameEnter = CreateTrigger()
MoveAbleFrame.TriggerFrameEnterAction = TriggerAddAction(MoveAbleFrame.TriggerFrameEnter, function()
if GetLocalPlayer() == GetTriggerPlayer() then
MoveAbleFrame.PlayerHoveredFrame = BlzGetTriggerFrame()
end
end)
MoveAbleFrame.TriggerFrameLeave = CreateTrigger()
MoveAbleFrame.TriggerFrameLeaveAction = TriggerAddAction(MoveAbleFrame.TriggerFrameLeave, function()
if GetLocalPlayer() == GetTriggerPlayer() then
MoveAbleFrame.PlayerHoveredFrame = nil
end
end)
MoveAbleFrame.MouseClickTrigger = CreateTrigger()
MoveAbleFrame.MouseClickTriggerAction = TriggerAddAction(MoveAbleFrame.MouseClickTrigger, function()
if BlzGetTriggerPlayerMouseButton() == MOUSE_BUTTON_TYPE_RIGHT then
local player = GetTriggerPlayer()
if MoveAbleFrame.PlayerHoveredFrame then
--UI Edit Mode start moving that frame
if MoveAbleFrame.Enabled then
if GetLocalPlayer() == player then
MoveAbleFrame.startMoving(MoveAbleFrame.PlayerHoveredFrame)
--disable the moving frame so it does not send mouse enter events, is more accurate to move and other frames are better respecected
BlzFrameSetEnable(MoveAbleFrame.PlayerHoveredFrame, false)
end
end
end
end
end)
MoveAbleFrame.MouseReleaseTrigger = CreateTrigger()
MoveAbleFrame.MouseReleaseTriggerAction = TriggerAddAction(MoveAbleFrame.MouseReleaseTrigger, function()
if BlzGetTriggerPlayerMouseButton() == MOUSE_BUTTON_TYPE_RIGHT then
--reenable the movedFrame, if there is one
if MoveAbleFrame.Frame then
BlzFrameSetEnable(MoveAbleFrame.Frame, true)
end
--UI Edit Mode start moving that frame
FrameGrid.show(false, GetTriggerPlayer())
end
end)
for playerIndex = 0, GetBJMaxPlayers()-1,1 do
TriggerRegisterPlayerEvent(MoveAbleFrame.MouseClickTrigger, Player(playerIndex), EVENT_PLAYER_MOUSE_DOWN)
TriggerRegisterPlayerEvent(MoveAbleFrame.MouseReleaseTrigger, Player(playerIndex), EVENT_PLAYER_MOUSE_UP)
end
end, err)
end)