Gui.set_screen_position() and gui.screen_pos_to_node_pos()

This is implementation of gui.set_screen_position() and gui.screen_pos_to_node_pos() functions for Defold. This library will be useful if you want to get screen position of the node and set this position for another node with the different parent of even in another component.

Installation

You can use this library in your own project by adding this project as a Defold library dependency. Open your game.project file and in the dependencies field under project add:

https://github.com/AGulev/set_screen_position/archive/master.zip

First of all, we need to recalculate all coefficient when you change screen size, that why we need to add a few lines into render_script:

-- require the module
local gui_extra_functions = require "gui_extra_functions.gui_extra_functions"
...
function init(self)
  ...
  -- calculate coefficients when init the game
  gui_extra_functions.update_coef(render.get_window_width(), render.get_window_height())
end
...

function on_message(self, message_id, message)
  ...
  -- calculate coefficients when changing screen size
elseif message_id == hash("window_resized") then
  gui_extra_functions.update_coef(render.get_window_width(), render.get_window_height())
elseif
...
end

Without Layouts

If you don’t use layouts, then just call init() method in any gui_script:

-- any gui_script file
local gui_extra_functions = require "gui_extra_functions.gui_extra_functions"
...
function init(self)
  ...
  gui_extra_functions.init()
end

With Layouts

We need to call init() method in any gui_script with all possible options for layouts:

-- any gui_script file
local gui_extra_functions = require "gui_extra_functions.gui_extra_functions"
...
function init(self)
  ...
  -- table with layouts should have next format:
  -- {[hashed_layout_id] = {width = layout_width, height = layout_height} }
  gui_extra_functions.init({
    [hash("Standard")] = {
      width = 960,
      height = 640
    },
    [hash("Portrait")] = {
      width = 720,
      height = 1280
    },
    [hash("Landscape")] = {
      width = 1280,
      height = 720
    },
  })
end

Usage

-- get screen position of the node
local screen_pos = gui.get_screen_position(some_node_with_difficult_hierarchy)

-- set screen position for another node
gui.set_screen_position(some_other_node, screen_pos)

-- or convert screen position to position relative to this node,
-- for example,  for gui.animate()
local local_node_pos = gui.screen_pos_to_node_pos(screen_pos, some_other_node)
gui.animate(animation_node, gui.PROP_POSITION, local_node_pos, gui.EASING_LINEAR, 1)

Thanks, @ross.grams for his functions for different adjust modes and @britzl for help with gui.set_parent() logic (magic).

11 Likes

Sorry for bumping an old topic, but I needed to thank AGulev for this :pray:

(and all the other stuff that make my developer journey way less painful)

2 Likes

I’ve been using this extension in all my projects, it’s wonderful.

I’m seeing an issue when using gui.set_screen_position() on nodes with a different pivot than center:

This is the code:

local screen_position = gui.get_screen_position(node)
screen_position.x = screen_position.x + action.screen_dx
screen_position.y = screen_position.y + action.screen_dy
gui.set_screen_position(node, screen_position)

Is there something I can do to prevent this? I’m using the extension to be able to use screen_dx and screen_dy directly, rather than using gui.set_position() and (somehow) calculating the difference.

Tiny project: Set Screen Position on Pivot Nodes.zip (5.1 KB)

1 Like

It is not entirely clear to me what is wrong by looking at the video. Aren’t the nodes with different pivot supposed to move away like they do?

1 Like

I expect all nine nodes to be dragged in the same way as the center node. The same code is used to move all nodes.

Is there a reason why the gui.set_screen_position() works differently when the only difference is the pivot point?

gui.get_screen_position() ignores node’s pivot.
I didn’t know that. As result, you get screen position without pyvot and set it using set_screen_position() which uses pivot (it is set_position() with a couple of tricks inside).

The simplest solution here is using parent node for moving all nodes together (add the mto parent node, move, then remove from the parent node).

But if you want I cat add method that add pivot calculations.

UPD: I’ll fix it in the lib in a while

1 Like

Please check this version.

This is a breaking change and it needs just for some cases, so I make it optional
gui.set_screen_position(node, screen_position, recalculate_pivot)
in your case recalculate_pivot should be true

Brilliant, thanks! Works perfectly.

ps. Also loving the new release tag on Github, feels safer somehow. :slight_smile:

2 Likes