WoW:API Region SetPoint: Difference between revisions

From AddOn Studio
Jump to navigation Jump to search
(tweak header)
Line 29: Line 29:
* x and y units are relative to the screen's effective scale. WoW's screen always has a height of 768 units, width varies with aspect ratio.
* x and y units are relative to the screen's effective scale. WoW's screen always has a height of 768 units, width varies with aspect ratio.


* As of 1.11 or so, there seems to be an [[API Region SetPoint/Exponential time|exponential-time increase]] if you anchor chains of objects with more than one point.
* As of 1.11 or so, there seems to be an [[API Region SetPoint#Exponential time|exponential-time increase]] if you anchor chains of objects with more than one point.


* As of 2.2 the screen coordinates are no longer relative to the TOPLEFT instead they are relative to closest screen position which can be TOPLEFT, TOP, TOPRIGHT, LEFT, CENTER, RIGHT, BOTTOMLEFT, BOTTOM and BOTTOMRIGHT be sure to specify the relativePoint argument, wich you can get via [[API Region GetPoint|GetPoint()]], or your frames will appear at the wrong place and even off the screen.
* As of 2.2 the screen coordinates are no longer relative to the TOPLEFT instead they are relative to closest screen position which can be TOPLEFT, TOP, TOPRIGHT, LEFT, CENTER, RIGHT, BOTTOMLEFT, BOTTOM and BOTTOMRIGHT be sure to specify the relativePoint argument, wich you can get via [[API Region GetPoint|GetPoint()]], or your frames will appear at the wrong place and even off the screen.
== Exponential time ==
As of approximately v1.11, creating a chain of relative positioning, where more than one SetPoint() call is done on a number of frames (i.e. the next frame has its size ''and'' position dependent on the previous one), causes '''exponential execution time''' during SetPoint() calls.
=== Multiple chained SetPoint() calls causing exponential execution time ===
Consider the below code, which creates a stack of frames, each 100 pixels wide and 10 pixels high, with 2 pixels of spacing between them:
first = CreateFrame("Frame", UIParent);
first:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", 700, 500);
first:SetWidth(100);
first:SetHeight(10);
prev=first;
for i=1,NUMFRAMES do
  f = CreateFrame("Frame", UIParent);
  f:SetPoint("TOPLEFT", prev, "BOTTOMLEFT", 0, -2);
  f:SetPoint("TOPRIGHT", prev, "BOTTOMRIGHT", 0, -2);
  f:SetHeight(10);
  prev=f;
end
endTime = GetTime();
Timing results for different numbers of frames chained:
  19:  0.3s
  20:  0.6s
  21:  1.3s
  22:  2.6s
  23:  5.2s
  24: 10.4s
  25: 20.8s
* The original snippet feeds information for the same edge (TOP) twice, but the below code, which avoids doing that, has the exact same results:
  f:SetPoint("TOPLEFT", prev, "BOTTOMLEFT", 0, -2);
  f:SetPoint("'''RIGHT'''", prev, "'''RIGHT'''", 0, 0);
* Referencing the same corner in both calls also has the same results:
  f:SetPoint("TOPLEFT", prev, "'''TOPLEFT'''", 0, -12);
  f:SetPoint("TOPRIGHT", prev, "'''TOPLEFT'''", 100, -12);
=== Solutions ===
* However, chaining only ONE SetPoint from object to object, and referencing the first object for the second SetPoint, executes faster than GetTime() can measure even for dozens of objects:
  f:SetPoint("TOPLEFT", prev, "BOTTOMLEFT", 0, -2);
  f:SetPoint("RIGHT", '''first''', "RIGHT", 0,0);
* This code also executes in "0 seconds":
  f:SetPoint("TOPLEFT", prev, "BOTTOMLEFT", 0, -2);
  '''f:SetWidth(100);'''
Timing the two problematic SetPoint() calls, they both take the same time (i.e. 1.3s each on the 23rd loop). Nothing else in the loop is taking any discernible amount of time.

Revision as of 01:19, 2 November 2008

Widget API ← Region < SetPoint

Sets the current attachment point of an UI component.

obj:SetPoint(point [, frame] [, relativePoint] [, x [, y]]);

Parameters

Arguments

point
The point on your object to use for attaching the obj (see API Positions) (i.e. bind the left side of your frame)
frame
Name of, or reference to, a frame to attach obj to; or nil to anchor relative to obj's parent (if no parent exists, anchor reative to the whole screen).
relativePoint
The relative point of frame to attach obj to (see API Positions); if not specified, defaults to the value of point when not specified.
x
x-offset (negative values will move obj left, positive values will move obj right), defaults to 0 if not specified.
y
y-offset (negative values will move obj down, positive values will move obj up), defaults to 0 if not specified.

Examples

The following are all equivalent.

MainMenuBar:SetPoint("BOTTOMLEFT", "UIParent", "BOTTOMLEFT", 0, 0);
MainMenuBar:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", 0, 0);
MainMenuBar:SetPoint("BOTTOMLEFT", "UIParent", "BOTTOMLEFT");
MainMenuBar:SetPoint("BOTTOMLEFT", "UIParent");

The following is equivalent to the above, given that the parent frame of MainMenuBar is UIParent.

MainMenuBar:SetPoint("BOTTOMLEFT");
MainMenuBar:SetPoint("BOTTOMLEFT", 0, 0);

Details

  • You will have to do a obj:ClearAllPoints() before using obj:SetPoint(...), if you expect the frame to actually move.
  • x and y units are relative to the screen's effective scale. WoW's screen always has a height of 768 units, width varies with aspect ratio.
  • As of 2.2 the screen coordinates are no longer relative to the TOPLEFT instead they are relative to closest screen position which can be TOPLEFT, TOP, TOPRIGHT, LEFT, CENTER, RIGHT, BOTTOMLEFT, BOTTOM and BOTTOMRIGHT be sure to specify the relativePoint argument, wich you can get via GetPoint(), or your frames will appear at the wrong place and even off the screen.

Exponential time

As of approximately v1.11, creating a chain of relative positioning, where more than one SetPoint() call is done on a number of frames (i.e. the next frame has its size and position dependent on the previous one), causes exponential execution time during SetPoint() calls.

Multiple chained SetPoint() calls causing exponential execution time

Consider the below code, which creates a stack of frames, each 100 pixels wide and 10 pixels high, with 2 pixels of spacing between them:

first = CreateFrame("Frame", UIParent);
first:SetPoint("TOPLEFT", UIParent, "BOTTOMLEFT", 700, 500);
first:SetWidth(100);
first:SetHeight(10);
prev=first;
for i=1,NUMFRAMES do
  f = CreateFrame("Frame", UIParent);
  f:SetPoint("TOPLEFT", prev, "BOTTOMLEFT", 0, -2);
  f:SetPoint("TOPRIGHT", prev, "BOTTOMRIGHT", 0, -2); 
  f:SetHeight(10);
  prev=f;
end
endTime = GetTime();

Timing results for different numbers of frames chained:

 19:  0.3s
 20:  0.6s
 21:  1.3s
 22:  2.6s
 23:  5.2s
 24: 10.4s
 25: 20.8s


  • The original snippet feeds information for the same edge (TOP) twice, but the below code, which avoids doing that, has the exact same results:
  f:SetPoint("TOPLEFT", prev, "BOTTOMLEFT", 0, -2);
  f:SetPoint("RIGHT", prev, "RIGHT", 0, 0); 


  • Referencing the same corner in both calls also has the same results:
  f:SetPoint("TOPLEFT", prev, "TOPLEFT", 0, -12);
  f:SetPoint("TOPRIGHT", prev, "TOPLEFT", 100, -12);


Solutions

  • However, chaining only ONE SetPoint from object to object, and referencing the first object for the second SetPoint, executes faster than GetTime() can measure even for dozens of objects:
  f:SetPoint("TOPLEFT", prev, "BOTTOMLEFT", 0, -2);
  f:SetPoint("RIGHT", first, "RIGHT", 0,0);


  • This code also executes in "0 seconds":
  f:SetPoint("TOPLEFT", prev, "BOTTOMLEFT", 0, -2);
  f:SetWidth(100);


Timing the two problematic SetPoint() calls, they both take the same time (i.e. 1.3s each on the 23rd loop). Nothing else in the loop is taking any discernible amount of time.