Quantcast Function to setup dragging & save the vars - WoWInterface
Thread Tools Display Modes
08-20-17, 07:37 PM   #1
stako
A Deviate Faerie Dragon
 
stako's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 10
Function to setup dragging & save the vars

Hello,

I'm sure everybody is familiar with making a frame movable and saving its position by doing something like this:

Lua Code:
  1. frame:SetScript("OnMouseDown", function()
  2.     if not frame.isMoving then
  3.         frame:StartMoving()
  4.         frame.isMoving = true
  5.     end
  6. end)
  7.  
  8. frame:SetScript("OnMouseUp", function()
  9.     if frame.isMoving then
  10.         frame:StopMovingOrSizing()
  11.         frame.isMoving = false
  12.        
  13.         MyAddon.db.profile.position = {frame:GetPoint()}
  14.     end
  15. end)

Now I'm doing this for numerous frames, so I'm trying to make a function out of it:

Lua Code:
  1. function MyAddon:SetupDrag(frame, dbsetting)
  2.     frame:SetScript("OnMouseDown", function()
  3.         if not frame.isMoving then
  4.             frame:StartMoving()
  5.             frame.isMoving = true
  6.         end
  7.     end)
  8.  
  9.     frame:SetScript("OnMouseUp", function()
  10.         if frame.isMoving then
  11.             frame:StopMovingOrSizing()
  12.             frame.isMoving = false
  13.            
  14.             -- Parameters get passed as values, so this won't work
  15.             -- dbsetting = {frame:GetPoint()}
  16.            
  17.             -- This works
  18.             dbsetting[1], dbsetting[2], dbsetting[3], dbsetting[4], dbsetting[5] = frame:GetPoint()
  19.         end
  20.     end)
  21. end

And example function call:
MyAddon:SetupDrag(ExampleFame, MyAddon.db.profile.position)

This works a little. Once I reset or change Ace profiles, it stops functioning. I think after the profile changes, MyAddon.db.profile.position will reference properly, but dbsetting will not?

Can't figure out a fix for that. Any ideas?
  Reply With Quote
08-21-17, 07:27 AM   #2
MunkDev
A Scalebane Royal Guard
 
MunkDev's Avatar
AddOn Author - Click to view addons
Join Date: Mar 2015
Posts: 427
It's fine to alter a table in one place and maintain a reference to it in another place, as long as you don't replace the table as a whole. Your variables are just pointers to the same object in memory. The code you posted isn't enough to figure out the cause.
__________________
  Reply With Quote
08-23-17, 04:14 AM   #3
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 1,920
Long story short, the variables don't actually store the table itself. They store a pointer that tells Lua where the table data is. This means when the Ace profile changes, dbsetting remains pointing to the old table. You need to call MyAddon:SetupDrag() again to update, but there is already an inherent problem in doing so. You're wasting resources dynamically creating new functions every time you call it. To prevent this, you should create static versions of them as upvalues so they don't get recreated constantly. To handle saving their positions, each frame called in the code below will store a reference to its own profile table. Again, you still need to call MyAddon:SetupDrag() each time the profile changes to update these references.

Lua Code:
  1. local function Frame_OnMouseDown(self)
  2.     if not self.isMoving then  
  3.         self:StartMoving()
  4.         self.isMoving = true
  5.     end
  6. end
  7.  
  8. local function Frame_OnMouseUp(self)
  9.     if self.isMoving then
  10.         self:StopMovingOrSizing()
  11.         self.isMoving = false
  12.  
  13.         self.settings[1], self.settings[2], self.settings[3], self.settings[4], self.settings[5] = self:GetPoint(1)
  14.     end
  15. end
  16.  
  17. function MyAddon:SetupDrag(frame, settings)
  18.     frame.settings=settings
  19.     frame:SetScript("OnMouseDown", Frame_OnMouseDown)
  20.     frame:SetScript("OnMouseUp", Frame_OnMouseUp)
  21. end

PS: frame:GetPoint() needs an index saying which point you want. I'm surprised this hasn't thrown an error.
__________________
ESOUI AddOns | WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)
  Reply With Quote
08-23-17, 03:52 PM   #4
stako
A Deviate Faerie Dragon
 
stako's Avatar
AddOn Author - Click to view addons
Join Date: Oct 2008
Posts: 10
Thank you very much!

Also hadn't even thought about GetPoint() needing an argument. I think I can use GetCenter() instead.
  Reply With Quote
08-23-17, 09:11 PM   #5
SDPhantom
A Pyroguard Emberseer
 
SDPhantom's Avatar
AddOn Author - Click to view addons
Join Date: Jul 2006
Posts: 1,920
Be aware if you use frame:GetCenter(), the numbers you get may be raw coordinates not taking into account UI scaling or anchor offsets. In this case, it's based off the coordinates at the bottom left corner of the screen. To reapply these numbers, the point you set would have to be the center of the frame. When you apply a profile change for example, be sure to call frame:ClearAllPoints() to make sure if the UI moved which point was set when dragged around, it wouldn't cause any further problems before setting the new position.

It might be better in the long run instead of frame:GetPoint() since saved vars can't store frame references, which would be its second return.
__________________
ESOUI AddOns | WoWInterface AddOns
"All I want is a pretty girl, a decent meal, and the right to shoot lightning at fools."
-Anders (Dragon Age: Origins - Awakening)

Last edited by SDPhantom : 08-23-17 at 09:14 PM.
  Reply With Quote

WoWInterface » Developer Discussions » Lua/XML Help » Function to setup dragging & save the vars

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off