11-04-10, 10:22 AM | #1 |
Odd Issue with Re-Positioning via Points
The Problem:
The best way to illustrate this problem is with some images. I'm going to link them rather than post them in here due to their size. The first image shows the default setup of my Rune bar for the AddOn. As you can see, there are 3 rows with 2 columns: 3 Rows - 2 Columns Next, as you can see, I'm working on offering alternative layout arrangements, including allowing users to simply move the Runes to their own individual locations. However, before I take that last step, I'd like to offer users the ability to have some "stock" layout arrangements that they can choose quickly rather than have to setup manually. You can see those here: Layout Options For the purposes of this we'll choose the 2 rows and 3 columns option, but it should be noted that this problem happens across all options. Now, as you can see in the next two pictures, we've chosen 2 rows and 3 columns, but it's not quite setup like that. Rather, runes 2 and 3 seem to be at the bottom-right corner of rune 1. Runes 4 and 5 seem to be at the bottom-right corner of 2 and 3 and rune 6 is at the bottom right corner of runes 4 and 5: 2-3 Options 2 Rows - 3 Columns (broken) This would lead one to believe that something must have happened, somewhere in my code, where I set them to topleft - bottomright, correct? Except, if we do a /reload, as I've done for this final image, everything is setup correctly: 2 Rows - 3 Columns (fixed) The logical assertion that follows is that perhaps there's something different between the code that initially lays out my runes and the code that dynamically shifts them, but that's not the case at all, here are the two: The Code: The bolded sections are relevant to the placement of the frames: Initial Setup: Code:
local function SetRuneFrames() local img = IMG..PowerBarsDB.PowSet.PowIMG; if not PowerBars.Runes then PowerBars.Runes = {} local Runes = PowerBars.Runes; local Frame = PowerBarsDB.PowSet.Frame[1]; local Base = PowerBars.Base.Resource.Frame; for i=1,6 do Runes[i] = {}; local RuneF = PowerBarsDB.PowSet.Frame[i+2]; local Rune = Runes[i]; Rune.Frame = CreateFrame("FRAME", nil, Base); Rune.Frame:SetSize(RuneF.Width, RuneF.Height); if i == 1 then Rune.Frame:SetPoint(RuneF.Point); elseif i % 2 == 0 then Rune.Frame:SetPoint(RuneF.Point, Runes[i-1].Frame, RuneF.RelativePoint); else if PowerBarsDB.Options.DEATHKNIGHT.Layout == 3 or PowerBarsDB.Options.DEATHKNIGHT.Layout == 4 then Rune.Frame:SetPoint(RuneF.Point, Runes[i-1].Frame, RuneF.RelativePoint); else Rune.Frame:SetPoint(RuneF.Point, Runes[i-2].Frame, RuneF.RelativePoint); end end Rune.Frame.Texture = Rune.Frame:CreateTexture(nil, "BACKGROUND"); local Texture = Rune.Frame.Texture Texture:SetAllPoints(Rune.Frame); local currRune = GetRuneType(i) or i; Texture:SetTexture(img..currRune); Rune.Frame.Cooldown = CreateFrame("Cooldown", nil, Rune.Frame); local Cooldown = Rune.Frame.Cooldown; Cooldown:SetAllPoints(Rune.Frame); Cooldown:SetFrameStrata("LOW"); if IsAddOnLoaded("OmniCC") then PowerBars.Class.DEATHKNIGHT.Check.OmniCC:Enable(); if PowerBarsDB.Options.DEATHKNIGHT.OmniCC == 1 then Cooldown.noCooldownCount = false; else Cooldown.noCooldownCount = true; end else PowerBars.Class.DEATHKNIGHT.Check.OmniCC:Disable(); end Cooldown.currCD = 0; Cooldown.Frame = CreateFrame("FRAME", nil, Rune.Frame); local CDFrame = Cooldown.Frame; CDFrame:SetAllPoints(Rune.Frame); CDFrame:SetFrameStrata("MEDIUM"); CDFrame.Text = PowerBars:CreateFont(CDFrame, Cooldown.currCD, "DEFAULT", Cooldown:GetWidth()/2, 0, 0, "CENTER", {255,255,0,1}, "DRAWINGLAYER", "OUTLINE"); local Text = CDFrame.Text; Text:SetAllPoints(CDFrame); CDFrame:Hide(); Rune.Timer = RuneTimer(i); end end end Dynamic Placement after Setup: Code:
local function doRuneFrames() local Runes = PowerBars.Runes; local Base = PowerBars.Base.Resource.Frame; local Frame = PowerBarsDB.PowSet.Frame[1]; for i=1,6 do local Rune = Runes[i]; local RuneF = PowerBarsDB.PowSet.Frame[i+2]; Rune.Frame:SetSize(RuneF.Width, RuneF.Height); if i == 1 then Rune.Frame:SetPoint(RuneF.Point); elseif i % 2 == 0 then Rune.Frame:SetPoint(RuneF.Point, Runes[i-1].Frame, RuneF.RelativePoint); else if PowerBarsDB.Options.DEATHKNIGHT.Layout == 3 or PowerBarsDB.Options.DEATHKNIGHT.Layout == 4 then Rune.Frame:SetPoint(RuneF.Point, Runes[i-1].Frame, RuneF.RelativePoint); else Rune.Frame:SetPoint(RuneF.Point, Runes[i-2].Frame, RuneF.RelativePoint); end end end end function DKLayout.SelectLayout(self, arg1) local Frame = PowerBarsDB.PowSet.Frame; local Settings = PowerBars.Defaults.DEATHKNIGHT.Settings[1]; UIDropDownMenu_SetSelectedID(DKLayout, self:GetID()); if arg1 == "3-2" then PowerBarsDB.Options.DEATHKNIGHT.Layout = 1; Frame[1].Width = Settings.WIDTH; Frame[1].Height = Settings.HEIGHT; PowerBars.Base.Resource.Frame:SetSize(Frame[1].Width, Frame[1].Height); local Runes = PowerBars.Runes; for i=1,6 do local RuneF = PowerBarsDB.PowSet.Frame[i+2]; if i == 1 then RuneF.Point = "TOPLEFT"; elseif i % 2 == 0 then RuneF.Point = "LEFT"; RuneF.RelativePoint = "RIGHT"; else RuneF.Point = "TOP"; RuneF.RelativePoint = "BOTTOM"; end end doRuneFrames(); elseif arg1 == "2-3" then PowerBarsDB.Options.DEATHKNIGHT.Layout = 2; Frame[1].Width = Settings.HEIGHT; Frame[1].Height = Settings.WIDTH; PowerBars.Base.Resource.Frame:SetSize(Frame[1].Width, Frame[1].Height); local Runes = PowerBars.Runes; for i=1,6 do local RuneF = PowerBarsDB.PowSet.Frame[i+2]; if i == 1 then RuneF.Point = "TOPLEFT"; elseif i % 2 == 0 then RuneF.Point = "TOP"; RuneF.RelativePoint = "BOTTOM"; else RuneF.Point = "LEFT"; RuneF.RelativePoint = "RIGHT"; end end doRuneFrames(); elseif arg1 == "1-6" then PowerBarsDB.Options.DEATHKNIGHT.Layout = 3; Frame[1].Width = 240; Frame[1].Height = 40; PowerBars.Base.Resource.Frame:SetSize(Frame[1].Width, Frame[1].Height); local Runes = PowerBars.Runes; for i=1,6 do local RuneF = PowerBarsDB.PowSet.Frame[i+2]; local Rune = Runes[i]; if i == 1 then RuneF.Point = "TOPLEFT"; elseif i % 2 == 0 then RuneF.Point = "LEFT"; RuneF.RelativePoint = "RIGHT"; else RuneF.Point = "LEFT"; RuneF.RelativePoint = "RIGHT"; end end doRuneFrames(); elseif arg1 == "6-1" then PowerBarsDB.Options.DEATHKNIGHT.Layout = 4; Frame[1].Width = 40; Frame[1].Height = 240; PowerBars.Base.Resource.Frame:SetSize(Frame[1].Width, Frame[1].Height); local Runes = PowerBars.Runes; for i=1,6 do local RuneF = PowerBarsDB.PowSet.Frame[i+2]; local Rune = Runes[i]; if i == 1 then RuneF.Point = "TOPLEFT"; elseif i % 2 == 0 then RuneF.Point = "TOP"; RuneF.RelativePoint = "BOTTOM"; else RuneF.Point = "TOP"; RuneF.RelativePoint = "BOTTOM"; end end doRuneFrames(); elseif arg1 == "unlock" then print("Unlock not yet functional."); --PowerBarsDB.Options.DEATHKNIGHT.Layout = 5; end end However, as explained above are correctly saved. When a /reload is done, all of the runes are set in the proper position. Other Things of Note: It should be noted that I had this problem once before in my code. Initially, I allowed users to move and resize the base frame for my addon's display of resources. Because they might end up placing or resizing them in funky ways, I also added a "reset" button which would allow them to restore the initial size and placement values. Despite the initial size and placement values being correctly stored and set however, the frames would often resize, but not to the proper size, and not be placed in the proper position. If one did a /reload, then everything would be sized and placed as expected. In an attempt to fix the situation I eventually used setmovable and setresizeable in the code for the resetting, setting them to true in the beginning and then resetting them to false after. However, despite making the frames "movable" and "resizable" I still had the issue. It was eventually solved by changing the "resize" option to a "scale" option as the game seemed to have no issues setting it back to its correct scale and position. But, whereas the game had no issue setting back to the correct position before, unless the size was different, in this instance it seems that it does. I have not personally tried using setmovable in this specific instance yet, but I will try (even though the frames are clearly moving, just not to the proper places). It was also suggested by me to try and have the frames reset to a central location and use offsets to position them. I will try this as well, though, if it works, it still speaks to issues with dynamically anchoring off of set points. Hopefully someone will be able to help as I'd prefer to keep the setup that I have, it SHOULD be functional, but isn't. |
|
11-04-10, 10:30 AM | #2 |
jnwhiteh is the man! (or woman). I didn't use ClearAllPoints() (which explains why they didn't move properly when they did in my old example since I used the function in the old example).
It still doesn't explain why the old examples wouldn't resize properly, but that information isn't necessarily needed at the moment. It could be needed in the future though, so if anyone has any thoughts on it, please do share. |
|
11-04-10, 08:18 PM | #3 |
Yeah, frames can take multiple SetPoint() calls. This can also impact their size, and is usually used this way as such.
For example, if you want a texture behind your chat frame, but want to take into account any size the chat frame may be for all of your characters.... lua Code:
This will anchor the frame to the top left of the chat frame (with a padding of 3) and to the bottom right of the chat frame (with the same padding of 3). It doesn't matter how big the chat frame is, the frame/texture will always be the correct size. |
|
11-06-10, 05:38 PM | #4 | |
To add to this, you can get away with using frame:SetPoint() without calling frame:ClearAllPoints() as long as you keep referencing the same point on the frame you're setting. If you have 2 or more points set at the same time, WoW will try to resize the frame to obey all the points set.
__________________
WoWInterface AddOns
|
||
WoWInterface » Developer Discussions » Lua/XML Help » Odd Issue with Re-Positioning via Points |
«
Previous Thread
|
Next Thread
»
|
Display Modes |
Linear Mode |
Switch to Hybrid Mode |
Switch to Threaded Mode |
|
|