1. Head to the 33rd Modeling Contest Poll and drink to your heart's desire.
    Dismiss Notice
  2. Choose your means of doom in the 17th Mini Mapping Contest Poll.
    Dismiss Notice
  3. A slave to two rhythms, the 22nd Terraining Contest is here.
    Dismiss Notice
  4. The heavens smile on the old faithful. The 16th Techtree Contest has begun.
    Dismiss Notice
  5. The die is cast - the 6th Melee Mapping Contest results have been announced. Onward to the Hive Cup!
    Dismiss Notice
  6. The glory of the 20th Icon Contest is yours for the taking!
    Dismiss Notice
  7. Check out the Staff job openings thread.
    Dismiss Notice
Dismiss Notice
60,000 passwords have been reset on July 8, 2019. If you cannot login, read this.

UI: Positionate Frames

Discussion in 'JASS/AI Scripts Tutorials' started by Tasyen, May 29, 2019.

  1. Tasyen

    Tasyen

    Joined:
    Jul 18, 2010
    Messages:
    1,660
    Resources:
    37
    Tools:
    2
    Maps:
    3
    Spells:
    11
    Tutorials:
    20
    JASS:
    1
    Resources:
    37

    Introduction


    Frames positions are important and are the key to place frames where one wants them to be.

    To positionate frames there exist 4 natives. All 4 have great uses.
    Code (vJASS):

    native BlzFrameSetPoint takes framehandle frame, framepointtype point, framehandle relative, framepointtype relativePoint, real x, real y returns nothing
    native BlzFrameSetAbsPoint takes framehandle frame, framepointtype point, real x, real y returns nothing
    native BlzFrameClearAllPoints takes framehandle frame returns nothing
    native BlzFrameSetAllPoints takes framehandle frame, framehandle relative returns nothing
     

    To positionate frames one also needs the framepointtype constants.
    Code (vJASS):

     FRAMEPOINT_TOPLEFT
     FRAMEPOINT_TOP
     FRAMEPOINT_TOPRIGHT
     FRAMEPOINT_LEFT
     FRAMEPOINT_CENTER
     FRAMEPOINT_RIGHT
     FRAMEPOINT_BOTTOMLEFT
     FRAMEPOINT_BOTTOM
     FRAMEPOINT_BOTTOMRIGHT
     

    What the natives do?


    BlzFrameSetAbsPoint
    takes one point of a Frame unbound that point and places it to a specific coordinates on the screen.
    BlzFrameSetPoint
    places a point of FrameA relative to a point of FrameB. When FrameB moves FrameA's point will keep this rule and moves with it.
    BlzFrameClearAllPoints
    removes all curent bound points of that frame.
    BlzFrameSetAllPoints
    FrameA will copy FrameB in size and position. FrameA will update when FrameB is changed later.

    Cartesian coordinate system


    coordinates and offset are both a factor of the total screen. 0.0/0.0 beeing the bottom left corner of the 4:3 screen. 0.8/0.6 is the top right corner of the 4:3 screen.
    imgs

    Coords Image 56.jpg
    warcraft 3 coord system 3.jpg

    Positionating requiers the frame one wants to move and the FRAMEPOINT of that frame. One moves only the choosen FRAMEPOINT, if other FRAMEPOINTS are still located somewhere, the frame will be stretched to have both FRAMEPOINTS be filled as good that is possible, for a rectangle. This can (sometimes has to) be used to define size of frames.
    Here one should positionate either
    FRAMEPOINT_TOPRIGHT and FRAMEPOINT_BOTTOMLEFT
    or
    FRAMEPOINT_TOPLEFT and FRAMEPOINT_BOTTOMRIGHT
    of the frame one wants to set its size.

    When placing only one FramePoint the choosen FramePoint has a strong impact on the result. It limites the directions size/text can expand.
    When using a point containing:
    LEFT can only extend to the right x wise.
    RIGHT can only extend to the left x wise.
    CENTER extends equal in all directions
    TOP can only extend downwards y wise
    BOTTOM can only extend upwards y wise.​
    Extend Frame.jpg

    If one simply wants to move a frame having a size one should first use BlzFrameClearAllPoints to free already placed Points.

    SetPoint requires the relative frame to take space on the screen, that relative frame can be set on a later time, but until that happens the moved frame will displayed wierdly or not all.​

    Relative Position


    Frames that belong logical to some other Frame benefit much when one sets their position relative to that frame they belong to or relative to a frame that is relative to the owner that could be contiuned, but in the end it is relative to the Owner Frame. This relative position is updated when the other Frame is moved. Because of that one only needs to set the position of the not relative posed Frame in that group and everything moves with it. In code the native doing that is
    BlzFrameSetPoint
    .
    Setting Relative position is a little bit inversed. when one was to place something left to something one needs to place the right side (of the moving) to the left of the target.
    Left to Right.jpg
    Code (vJASS):
    BlzFrameSetPoint(frameLeft, FRAMEPOINT_RIGHT, frameTarget, FRAMEPOINT_LEFT, 0, 0)
    BlzFrameSetPoint(frameRight, FRAMEPOINT_LEFT, frameTarget, FRAMEPOINT_RIGHT, 0, 0)

    The x and y offset in BlzFrameSetPoint are added to the target Point. with +x the position anchored to is moved further to the right and with +y it is moved higher up.
    Relative Offset.jpg Relative Offset - xy.jpg


    In Fdf one can only set position relative. But in Code one can also place them to a fixed position.​


    Example


    Lets move the menu button somewhere else, somewhere to the right top corner.
    Code (vJASS):

    function ReposMenuButtons takes nothing returns nothing
       local framehandle fh = BlzGetFrameByName("UpperButtonBarMenuButton",0)
       call BlzFrameSetAbsPoint(fh, FRAMEPOINT_RIGHT, 0.5, 0.5)
    endfunction
     

    Unwanted Result.jpg
    Not what we wanted. The Menu button stretched far to the right, pushed the Allies & Log button to the right and did not move lower. It seems his left side is still connected to the Quest button.


    It should work better, if we clear the points of Menu button.
    Code (vJASS):

    function ReposMenuButtons2 takes nothing returns nothing
       local framehandle fh = BlzGetFrameByName("UpperButtonBarMenuButton",0)
       call BlzFrameClearAllPoints(fh)
       call BlzFrameSetAbsPoint(fh, FRAMEPOINT_RIGHT, 0.5, 0.5)
    endfunction
     

    more wanted Result.jpg
    Well the Menu button moved, also the Allies & Log buttons, the texts are bit off, but it moved away from the Quest button and is not stretched.


    Lets move the Allies button below the Menu button and the Log button below the Allies button.
    Code (vJASS):

    function ReposMenuButtons3 takes nothing returns nothing
       local framehandle allies = BlzGetFrameByName("UpperButtonBarAlliesButton",0)
       local framehandle menu = BlzGetFrameByName("UpperButtonBarMenuButton",0)
       local framehandle log = BlzGetFrameByName("UpperButtonBarChatButton",0)
       call BlzFrameClearAllPoints(allies)
       call BlzFrameClearAllPoints(log)
       call BlzFrameClearAllPoints(menu)
       call BlzFrameSetAbsPoint(menu, FRAMEPOINT_RIGHT, 0.5, 0.5) //Pos Menu
       call BlzFrameSetPoint(allies, FRAMEPOINT_TOP, menu, FRAMEPOINT_BOTTOM, 0.0, 0.0) //Pos allies below menu
       call BlzFrameSetPoint(log, FRAMEPOINT_TOP, allies, FRAMEPOINT_BOTTOM, 0.0, 0.0) //Pos log below allies
    endfunction
     

    wanted Result.jpg
    Menu Allies and Log in a col, text is where it should be, I like it.

    They are to much in the center, but that is cause we moved menu with FRAMEPOINT_RIGHT. And cause of the wrong information of the total x size, the missinformation was 0.6 as max of the 4:3, but 0.8 is the right end of the 4:3 Screen not 0.6. 0.5 is much nearer to 0.4 then to 0.8 why it is more centered.​

    Frame Pos in FDF


    When one creates frames in fdf one can also set the position of frames. Here one has 3 options:
    SetPoint FramePoint-Own, FrameName, FramePoint-FrameName, xOffset , yOffset,
    SetAllPoints,
    Anchor FramePoint, x, y, (only SimpleFrames)​
    SetPoint can be seen as
    BlzFrameSetPoint(self, FramePoint-Own, BlzGetFrameByName(FrameName, 0), FramePoint-FrameName, x, y)
    . With UseActiveContext, the Frame will connect to the relative Frame with the same CreateContext the current Frame is created with.
    Code (Text):
    Frame "BACKDROP" "Test" {
        Width 0.1,
        Height 0.1,
        SetPoint TOPLEFT, "ConsoleUI", TOPLEFT, 0, 0,
        BackdropBackground "ReplaceableTextures\CommandButtons\BTNHeroPaladin",
    }
    That Frame of type BACKDROP with Name Test would on it creation display a Paladin-Icon at Top Left of the screen (Would have to be loaded over a toc first).
    SetAllPoints is equal to BlzFrameSetAllPoints(self, parent).
    Anchor is BlzFrameSetPoint(self, point, parent, point, x, y).​


    Other UI-Frame Tutorials


     

    Attached Files:

    Last edited by a moderator: Oct 6, 2020
  2. purparisien

    purparisien

    Joined:
    Jul 17, 2011
    Messages:
    628
    Resources:
    49
    Models:
    26
    Icons:
    11
    Maps:
    12
    Resources:
    49
    Its look very interesting. Can you attach an exemple map as you did with your previous tuto ? I would like to test it out
     
  3. Tasyen

    Tasyen

    Joined:
    Jul 18, 2010
    Messages:
    1,660
    Resources:
    37
    Tools:
    2
    Maps:
    3
    Spells:
    11
    Tutorials:
    20
    JASS:
    1
    Resources:
    37
    A demo map was uploaded.
     
  4. purparisien

    purparisien

    Joined:
    Jul 17, 2011
    Messages:
    628
    Resources:
    49
    Models:
    26
    Icons:
    11
    Maps:
    12
    Resources:
    49
    Thanks you so much ! +rep
     
    Last edited: Jun 13, 2019
  5. purparisien

    purparisien

    Joined:
    Jul 17, 2011
    Messages:
    628
    Resources:
    49
    Models:
    26
    Icons:
    11
    Maps:
    12
    Resources:
    49
    Hey Tasyen, I like this system a lot. Is it possible to display ressources information in the menu and allies spaces, once we move the buttons away ? I would like to add more ressources in a map by using these spaces. Thanks
     
  6. Tasyen

    Tasyen

    Joined:
    Jul 18, 2010
    Messages:
    1,660
    Resources:
    37
    Tools:
    2
    Maps:
    3
    Spells:
    11
    Tutorials:
    20
    JASS:
    1
    Resources:
    37
    Yes, but that is only partly connceted to the positionate Frames tutorial.

    What you would have to do is creating an image and a text frame. You could either use simpleFrames or Frames.
    In simpleFrames you would give the simpleFrame an texture and a String child. The Texture would be the icon and the String the shown text. resourcebar.fdf shows that, although they did not gave the textures names which disallows changing the icon later on.
    With Frames you would need a Frame of Type "BACKDROP" and one of Type "TEXT".
     
  7. burner89

    burner89

    Joined:
    Mar 11, 2019
    Messages:
    31
    Resources:
    0
    Resources:
    0
    It it possible to move stuff outside of the 4:3 area? If so could you explain for a noob
     
  8. Tasyen

    Tasyen

    Joined:
    Jul 18, 2010
    Messages:
    1,660
    Resources:
    37
    Tools:
    2
    Maps:
    3
    Spells:
    11
    Tutorials:
    20
    JASS:
    1
    Resources:
    37
    It is possible for simpleFrames by using x values above 0.8 or below 0.0 . One has to consider that models are not simpleframes. Moving them outside of 4:3 will break shown cooldowns for item/command buttons. Also for the same reason one can not move out the 3d Face nor the minimap.

    Moves the MenuButton into the 16:9 top left corner.
    Code (vJASS):

    call BlzFrameSetAbsPoint(BlzGetOriginFrame(ORIGIN_FRAME_SYSTEM_BUTTON, 3), FRAMEPOINT_TOPLEFT, -0.14, 0.6)
     


    To move the minimap one has to define/move 2 points either BOTTOMLEFT and TOPRIGHT, or BOTTOMRIGHT and TOPLEFT. The rect they enclose is the clickable space of the minimap, its not the size of the minimap-model displayed.
     
  9. burner89

    burner89

    Joined:
    Mar 11, 2019
    Messages:
    31
    Resources:
    0
    Resources:
    0
    1) Is there a way to fix the broken cooldowns?

    2) How can I stretch a frame after having it positioned? I want to stretch the HP/Mana bars on the hero frame.
     
    Last edited: Jun 19, 2019
  10. Tasyen

    Tasyen

    Joined:
    Jul 18, 2010
    Messages:
    1,660
    Resources:
    37
    Tools:
    2
    Maps:
    3
    Spells:
    11
    Tutorials:
    20
    JASS:
    1
    Resources:
    37
    Do not move them into 16:9, No Idea.


    You can try out
    call BlzFrameSetSize(frame, x, y)
    often that works sometimes it does not. For some frames it works better by positionating BOTTOMLEFT and TOPRIGHT or BOTTOMRIGHT and TOPLEFT.

    One can stretch that bar with
    call BlzFrameSetSize(BlzGetOriginFrame(ORIGIN_FRAME_HERO_HP_BAR,0), 0.2, 0.01)
     
  11. DarkLigthing

    DarkLigthing

    Joined:
    Mar 19, 2018
    Messages:
    2
    Resources:
    1
    Maps:
    1
    Resources:
    1
    Why does it works wrong for me ? :(

    Annotation 2019-07-28 151713.png Annotation 2019-07-28 151805.png
     
  12. Tasyen

    Tasyen

    Joined:
    Jul 18, 2010
    Messages:
    1,660
    Resources:
    37
    Tools:
    2
    Maps:
    3
    Spells:
    11
    Tutorials:
    20
    JASS:
    1
    Resources:
    37
    When the function executes at map init, the text disposing happens also for me. With Elapsed game time 0.00 seconds the result is much better at least for me.
     
  13. iown_azz

    iown_azz

    Joined:
    Jun 16, 2008
    Messages:
    334
    Resources:
    0
    Resources:
    0
    The only issue I have with the -0.1 is that if you change the window size of Warcraft III as small as the ConsoleUI, then what is in the -0.1 is hidden. Anything that is not a child of ConsoleUI, when you put 0.0, 0.0 it snaps to the corner of the Window and moves when the Window is resized.

    I can't figure out how to make children of ConsoleUI child of the window ratio.
     
  14. Tasyen

    Tasyen

    Joined:
    Jul 18, 2010
    Messages:
    1,660
    Resources:
    37
    Tools:
    2
    Maps:
    3
    Spells:
    11
    Tutorials:
    20
    JASS:
    1
    Resources:
    37
    What Frame does that can you show a small example. I only know of some Frames following the WindowSize. Portrait somehow uses a different coord system, but it keeps at bottomLeft when posed at 0,0. Multiboard, LeaderBoard, HeroButtons (but only on init), TimerDialog are others I know of (they keep at top right/left), but I think there is game code doing that in the background and not really a frame api feature.

    Instead of using this -values one could create a fullscreen Frame and pos all your Frames relative to that Frame. The fullscreen would have to be frequently updated to be fullscreen with a fast running timer and be posed at the beginning to center so it expands in both directions equaly: Inside that Timer one updates the Size; the formular is not from me.
    BlzFrameSetSize(fullscreenFrame, BlzGetLocalClientWidth()/BlzGetLocalClientHeight()*0.6, 0.6)
     
    Last edited: Jul 23, 2020
  15. iown_azz

    iown_azz

    Joined:
    Jun 16, 2008
    Messages:
    334
    Resources:
    0
    Resources:
    0
    I'll make a video tomorrow
     
  16. Chaosy

    Chaosy

    Tutorial Reviewer

    Joined:
    Jun 9, 2011
    Messages:
    11,058
    Resources:
    18
    Icons:
    1
    Maps:
    1
    Spells:
    10
    Tutorials:
    6
    Resources:
    18
    Minor changes made, extremely useful and possibly one of the first ones needed when fiddling with the UI.

    Approved.
     
  17. Drake53

    Drake53

    Joined:
    Jan 1, 2018
    Messages:
    425
    Resources:
    0
    Resources:
    0
    Not sure if anyone cares but since it's related I'll post some research I did here that hasn't been mentioned yet. I only used abs points for my tests.

    When you set multiple points that 'conflict' with each other, there is a certain priority in which points are used for further calculations.
    This order is the same as in common.j, meaning that a lower index in
    ConvertFramePointType
    has a higher priority:
    TopLeft > Left > BottomLeft (left)
    Top > Center > Bottom (center X)
    TopRight > Right > BottomRight (right)
    TopLeft > Top > TopRight (top)
    Left > Center > Right (center Y)
    BottomLeft > Bottom > BottomRight (bottom)

    If at least two of the three horizontal or vertical points are set, the width or height is calculated based on these points, otherwise the width and height from
    BlzFrameSetSize
    is used.
    If all three are set (for horizontal: left, center, and right; for vertical: top, center, and bottom), the center point is ignored in width/height calculation.