GUI adjust questions - fit within available space? (more-or-less solved)

I would like to have a gui with a box that maintains its aspect ratio while filling as much of the available space as possible, but I haven’t been able to figure out any node settings or combination of nodes that does this.

  1. With a horizontal display proportion, and a square box set to “Fit”, I get this, matching what the .gui in the editor looks like:

  2. If I shrink the window vertically I get what I expect and want:

  3. But if I shrink it horizontally, the box shrinks based on the proportional scale of the window (compared to the project settings size), rather than the actual width & height.

  4. So, what I want is this: (instead of #3)

For the node to maintain it’s propertion/aspect-ratio, within the width & height of it’s parent (or the window if there’s no parent).

Is there any way to do this?

  • I’ve tried every combination of nested Stretch/Zoom/Fit nodes I can think of, no luck.
  • I can manually resize the node no problem, but that doesn’t update the layout of any children of that node, so I would have to manually, recursively resize every single child node, which sounds very painful.
1 Like

Related other questions:

  • Is there a way to have a menu bar that stretches to fit the width of the window, but doesn’t scale vertically?
  • Why isn’t “None” an available Adjust Mode -per node-? (only for the entire GUI)
  • Has anyone written their own GUI layout system, either with GUI nodes or Game Objects, to get around the limitations of Defold’s built-in GUI?

That would be easier to play with that if you share your project with this example.

2 Likes

Can probably be done by manually scaling width and then setting height to inverse GUI scale?

1 Like

@AGulev Good point! :slight_smile:
ross_gui_fit_test.zip (7.6 KB)

@Pkeod Yeah…the answer staring me in the face I guess. I’m just resisting manually scaling every node. :expressionless:

1 Like

Here is solution that uses Layouts (no code):
ross_gui_fit_test_fixed.zip (14.2 KB)


1 Like

Hmm, that’s pretty cool and would be perfect I think, buuut…it seems like Layouts have broken GUI Templates for years? :worried:

For me if I add a basic button template, the overriden properties are sometimes used and sometimes not? It kind of goes haywire.
ross_gui_fit_test_broken_again.zip (9.6 KB)


Yes, it is broken.
I don’t use templates because of that.

(btw, if I remember correctly it’ broken only in the editor and works fine when bundle, or vice versa)

Yeah, I guess if you had to pick, templates are just for convenience. Do you just copy-paste a lot then? Or clone_tree at runtime?

I copy-paste nodes in the editor.
In my UI system I need to specify all the nodes I want to use, so for me it doesn’t matter if it’s a template or just a couple of nodes (I think UI is the only place I use operator : ^___^ )

like this:

self.ui = {}
  local ui = self.ui
  ui.factory = ui_factory.new(self)

  ui.btn_buy_shuffle_1 = ui.factory:new_button("btn_buy_shuffle_1", on_btn_buy_shuffle, cfg.IAP_SMALL_PACK_SHUFFLES)
  ui.btn_buy_shuffle_2 = ui.factory:new_button("btn_buy_shuffle_2", on_btn_buy_shuffle, cfg.IAP_BIG_PACK_SHUFFLES)
  ui.btn_buy_shuffle_ad = ui.factory:new_button("btn_buy_shuffle_ad", on_btn_buy_shuffle_ad)
  ui.btn_cancel = ui.factory:new_button("btn_cancel", on_btn_cancel)
  ui.factory:new_back_handler(on_btn_cancel)

  ui.factory:new_text_field("txt_shuffle_title")
  ui.factory:new_text_field("txt_btn_video_ad")
  ui.factory:new_text_field("txt_50_profit")
3 Likes

I had the very same problem and have written a module that I have used successfully in my last app.
All children stay exactly where they are supposed to be.
Total Lua-newbie here, what do you folks think about my solution?

--[[
This module provides one way to scale a Gui scene to use as much screen estate as possible.
Useful for adapting to different screen sizes or when the user resizes the window on a Desktop.
Put all content as children in one box (the root) and scale this box.
Set "adjust mode" of the Gui scenes concerned to "disabled".
Use in init when no resizing can occur (Mobile), use when a resized window is detected (Desktop).
Tested on Android, Windows and Manjaro Linux (I have not got a Mac, but I expect it works as well).
]]


local M = {}

-- variables for the box
local box
local box_width
local box_height
local box_dimensions
-- variables for the target device/window
local target_width
local target_height
-- variables for the scaling factors
local scale_width
local scale_height
-- variables for the center of the device screen
local window_center_x
local window_center_y

function M.scalefactor()
	-- get the box node and its dimensions
	box = gui.get_node("box")
	box_dimensions = gui.get_size(box)
	box_width = box_dimensions.x
	box_height = box_dimensions.y
	-- get the device screen/window, its dimensions and its center
	target_width, target_height = window.get_size()
	window_center_x = target_width / 2
	window_center_y = target_height / 2
	-- calculate the scaling factors
	scale_width = target_width / box_width
	scale_height = target_height / box_height
	-- if the screen/window is wider than tall, the box can use the full height available
	-- so use the height factor for scaling, then center the box
	if scale_width >= scale_height then
		gui.set_scale(box, vmath.vector3(scale_height, scale_height, 0))
		gui.set_position(box, vmath.vector3(window_center_x, window_center_y, 0))
	end
	-- if the screen/window is higher than wide, the box must respect the width,
	-- so use the width factor for scaling, then center the box
	if scale_width < scale_height then
		gui.set_scale(box, vmath.vector3(scale_width, scale_width, 0))
		gui.set_position(box, vmath.vector3(window_center_x, window_center_y, 0))
	end

end


return M

here it is in a small demo:
scalingtestLandscape.zip (4.7 KB)

Oh, forgot Apple-support. Have uploaded new zip

3 Likes

Looks good! I gave the sample project a try and it seems to work really well. Cool.

1 Like

Thank you @britzl for having a look!

1 Like