GUI parenting causes confusing gui.get_position change?

When giving your GUI a parent, that gui’s position is now reported as a vector point RELATIVE to the origin point of the parent that you set it to when using gui.get_position.

As an example, say:

gui.set_positon(parent,vmath.vector3(100,0,0) -- set parent to (X_100,Y_0,Z_0)

gui.set_parent(funky,parent)                                      -- set funky's parent to parent
gui.set_position(funky,vmath.vector3(0,0,0))     -- set funky's position RELATIVE to the parent to (0,0,0), even though this will change nothing

My logic goes to think, “Ok, so funky will be found at (100,0,0) on the screen.” But this is not what happens. Gui.get_position now will report the position relative to the gui object, and no longer the screen. I don’t see much of an advantage this could give. For world objects I absolutely understand the power of it, but I think of gui objects of always being anchored to the screen, so this confuses me and makes on-the-fly menu building much more difficult.

At the moment, I’m applying gui objects to one “menu” which will form a tooltip. One is the background, a variable amount for the description text(s), and a variable amount for the buttons. I’m having trouble with this because I’m getting button presses by collision. I calculate the area by four points, and ask if the click point was within that. I use gui.get_position to find those collision points, and it makes it more confusing to have to throw in a loop hole, adding the parent’s position as well.

If there is powerful logic to this that makes this case insignificant, would you mind letting me know? I’m a bit confused why it would change, because it just makes more sense to keep it consistent and relative to the screen’s origin point.

1 Like

I’m thinking quite the opposite. When I build a collection of gui nodes (tooltip, floating menu, scroll list, grid of buttons etc) I attach the nodes to a parent object and then only care about the nodes’ relative positions within the parent. I can then move the parent node and children will follow. I also expect gui.get_position() to return the position of the node, relative to any parent. There is a gui.get_screen_position() that returns the position on screen, taking into account parent nodes.

1 Like

WARNING! From what I have observed gui.get_screen_position() returns the position in the device resolution. Meaning that if you have specified 720x1280 in your game.project file as your resolution, but you then run the game on phone with a resolution of 1440x2560 the top left corner will return 1440x2560, and not 720x1280 (which the gui works with) thus you can’t use that value directly with gui.set_position().

Let us say that you want to play a particlefx on a gui node, this gui node is a child to a lot of objects so you use gui.get_screen_position(node), you then set the position of your (orphan) particlefx to that value. In short we do this gui.set_position(particlefx, gui.get_screen_position(node))
The result you will get varies widely depending on your devices’ actual resolution. In the first example the actual position you will set the particlefx is two times the nodes actual position. While if you had a resolution that is 360x640 the position will be half of the nodes position.


If you want to do gui.set_position(particlefx, gui.get_screen_position(node)) you will first have to scale the screen_position x value with project_width/screen_width and y with project_height/screen_height. You need to store the values in a lua module from the render script with something like this gist https://gist.github.com/Jerakin/4b031707f4d973cf66d2c2e83068809d

Then use it in a gui_script like this

function init(self)
  self.project_width =  screeninfo.get_project_width()
  self.screen_width = screeninfo.get_window_width()
  self.project_height = screeninfo.get_project_height()
  self.screen_height = screeninfo.get_window_height()
end

local function update_position(self)
  local screen_pos = gui.get_screen_position(node)
  screen_pos.x = screen_pos.x * (self.project_width/self.screen_width)
  screen_pos.y = screen_pos.y * (self.project_height/self.screen_height)
  gui.set_position(particlefx,  screen_pos)
end

There is a ticket in for this (in my opinion) weird behaviour (DEF-2961).

3 Likes

@Gmanicus Why are you not using gui.pick_node()? You shouldn’t have to figure out a collision box yourself.

Incidentally, I’ve added a screen_to_gui coordinate transform function to Rendercam to help people fighting with the screen resolution vs. “logical” gui resolution thing, though I haven’t tested it on different mobile devices.

3 Likes

@britzl:

There is a gui.get_screen_position() that returns the position on screen, taking into account parent nodes.

That is what I’m looking for, but as @Mattias_Hedberg notes:

WARNING! From what I have observed gui.get_screen_position() returns the position in the device resolution.

Thank you for the warning. This would be a problem if I bundled the game onto a computer with a different screen resolution, correct?

@ross.grams:

Why are you not using gui.pick_node()? You shouldn’t have to figure out a collision box yourself.

That would certainly make things a bit easier! I can’t believe I missed that function. Thanks.

Incidentally, I’ve added a screen_to_gui coordinate transform function to Rendercam…

So the gui will now adapt correctly with different resolutions is what you’re saying?