WoW:API Region SetPoint: Difference between revisions

From AddOn Studio
Jump to navigation Jump to search
(tweak header)
m (Move page script moved page API Region SetPoint to API Region SetPoint without leaving a redirect)
 
(7 intermediate revisions by 6 users not shown)
Line 1: Line 1:
{{widgetmethod}}
{{widgetmethod}}
Sets an attachment point of an UI component.
obj:SetPoint(point, relativeFrame, relativePoint, ofsx, ofsy);
obj:SetPoint(point, relativeFrame, relativePoint);
obj:SetPoint(point, ofsx, ofsy);
obj:SetPoint(point);


Sets the current attachment point of an UI component.
== Arguments ==
obj:SetPoint(point [, frame] [, relativePoint] [, x [, y]]);
; point : String - Point of the object to adjust based on the anchor.
; relativeFrame : String/Widget - Name or reference to a frame to attach obj to. If omitted or nil, it typically defaults to the object's parent. However, if relativePoint is also not defined, relativeFrame will default to UIParent.
; relativePoint : String - point of the relativeFrame to attach point of obj to. If not specified, defaults to the value of point.
; ofsx : Number - x-offset (negative values will move ''obj'' left, positive values will move ''obj'' right), defaults to 0 if not specified.
; ofsy : Number - y-offset (negative values will move ''obj'' down, positive values will move ''obj'' up), defaults to 0 if not specified.


== Parameters ==
=== Points ===
=== Arguments ===
There are nine valid point values:
; point : The point on your object to use for attaching the obj (see [[API Positions]])  (i.e.  bind the left side of your frame)
* "TOP", "RIGHT" "BOTTOM" "LEFT": the center-points of the respective sides.
; 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).
* "TOPRIGHT", "TOPLEFT", "BOTTOMLEFT", "BOTTOMRIGHT": corners of the frame rectangle.
; 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.
* "CENTER": the center point of the frame rectangle.
; 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 ==
== Examples ==
Line 24: Line 31:


== Details ==
== Details ==
* Behavior of this function with multiple anchors is complex. Generally, you can override points by setting them again (so repeated assignment to the "TOPLEFT" point of a frame would move the frame, unless other anchor points interfere). If you're repositioning a frame, call <code>obj:[[API Region ClearAllPoints|ClearAllPoints]]()</code> to eliminate unwanted interactions.
* Offset units are relative to the screen's effective scale. WoW's screen always has a height of 768 units, while screen width varies with aspect ratio.
* <tt>ofsx</tt> and <tt>ofsy</tt> must both be passed as arguments for either to take effect; they default to 0 only when neither is given.  That is, <tt>foo:SetPoint(bar, 40)</tt> will ignore the 40 rather than treat it as (+40,+0).
* Secure frames will silently ignore calls to this function if the relative frame is a [[API FontString|FontString]].


* You will have to do a <code>obj:[[API Region ClearAllPoints|ClearAllPoints]]()</code> before using obj:SetPoint(...), if you expect the frame to actually move.
=== Edge definitions ===
The edge "points" (TOP, RIGHT, BOTTOM, LEFT) are not actual points, but... edges. To fully define a region position using edges alone, you will need to define all four (as opposed to using corners, where you only need two) edges.


* 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.
Therefore, defining an edge does not necessarily place a region relative to the center of that edge (For example, if you define TOP and RIGHT, the region will be placed at the TOPRIGHT corner). However, by default a region is "pulled" to the center if the number of points defined is insufficient.


* 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.
Example:
 
Region:ClearAllPoints();
* 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.
  Region:SetPoint("TOP", relativeframe);
 
  Region:SetWidth(100);
== Exponential time ==
  Region:SetHeight(100);
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.
will place ''Region'' to the top center of the ''relativeframe'' while adding a
 
Region:SetPoint("RIGHT", relativeframe);
=== Multiple chained SetPoint() calls causing exponential execution time ===
will place ''Region'' in the top right corner and now ''Region'' is fully defined.
 
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.

Latest revision as of 04:47, 15 August 2023

Widget API ← Region < SetPoint

Sets an attachment point of an UI component.

obj:SetPoint(point, relativeFrame, relativePoint, ofsx, ofsy);
obj:SetPoint(point, relativeFrame, relativePoint);
obj:SetPoint(point, ofsx, ofsy);
obj:SetPoint(point);

Arguments[edit]

point
String - Point of the object to adjust based on the anchor.
relativeFrame
String/Widget - Name or reference to a frame to attach obj to. If omitted or nil, it typically defaults to the object's parent. However, if relativePoint is also not defined, relativeFrame will default to UIParent.
relativePoint
String - point of the relativeFrame to attach point of obj to. If not specified, defaults to the value of point.
ofsx
Number - x-offset (negative values will move obj left, positive values will move obj right), defaults to 0 if not specified.
ofsy
Number - y-offset (negative values will move obj down, positive values will move obj up), defaults to 0 if not specified.

Points[edit]

There are nine valid point values:

  • "TOP", "RIGHT" "BOTTOM" "LEFT": the center-points of the respective sides.
  • "TOPRIGHT", "TOPLEFT", "BOTTOMLEFT", "BOTTOMRIGHT": corners of the frame rectangle.
  • "CENTER": the center point of the frame rectangle.

Examples[edit]

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[edit]

  • Behavior of this function with multiple anchors is complex. Generally, you can override points by setting them again (so repeated assignment to the "TOPLEFT" point of a frame would move the frame, unless other anchor points interfere). If you're repositioning a frame, call obj:ClearAllPoints() to eliminate unwanted interactions.
  • Offset units are relative to the screen's effective scale. WoW's screen always has a height of 768 units, while screen width varies with aspect ratio.
  • ofsx and ofsy must both be passed as arguments for either to take effect; they default to 0 only when neither is given. That is, foo:SetPoint(bar, 40) will ignore the 40 rather than treat it as (+40,+0).
  • Secure frames will silently ignore calls to this function if the relative frame is a FontString.

Edge definitions[edit]

The edge "points" (TOP, RIGHT, BOTTOM, LEFT) are not actual points, but... edges. To fully define a region position using edges alone, you will need to define all four (as opposed to using corners, where you only need two) edges.

Therefore, defining an edge does not necessarily place a region relative to the center of that edge (For example, if you define TOP and RIGHT, the region will be placed at the TOPRIGHT corner). However, by default a region is "pulled" to the center if the number of points defined is insufficient.

Example:

Region:ClearAllPoints();
Region:SetPoint("TOP", relativeframe);
Region:SetWidth(100);
Region:SetHeight(100);

will place Region to the top center of the relativeframe while adding a

Region:SetPoint("RIGHT", relativeframe);

will place Region in the top right corner and now Region is fully defined.