How do formspec coordinates work?

Post Reply
User avatar
Wuzzy
Member
Posts: 4786
Joined: Mon Sep 24, 2012 15:01
GitHub: Wuzzy2
IRC: Wuzzy
In-game: Wuzzy
Contact:

How do formspec coordinates work?

by Wuzzy » Post

How do formspec coordinates work?

I think I can kinda work with them but actually I don't have a clue what I am doing. I noticed that formspec coordinates of some formspec elements are not consistent and depend on the element type.
For instance, elements end up at different places for the same coordinates depending on whether it is a button or (text) field.

You can see an example of this in my mod “L-System Tree Utility”, you'll clearly notice the buttons and fields are not nicely aligned and I have no idea how to fix this. I have tried several offsets for the buttons but they just seem to make it worse, so I decided to leave it as it is now.
Image

The relevant code for this part of the formspec begins at line 272 in init.lua and is this:

Code: Select all

	return ""..
	"field[0.2,-3.5;11,10;axiom;Axiom;"..s(fields.axiom).."]"..
	"button[11,0.2;1,1;edit_axiom;+]"..
	"tooltip[edit_axiom;Opens larger text field for Axiom]"..
	"field[0.2,-2.5;11,10;rules_a;Rules set A;"..s(fields.rules_a).."]"..
	"button[11,1.2;1,1;edit_rules_a;+]"..
	"tooltip[edit_rules_a;Opens larger text field for Rules set A]"..
	"field[0.2,-1.5;11,10;rules_b;Rules set B;"..s(fields.rules_b).."]"..
	"button[11,2.2;1,1;edit_rules_b;+]"..
	"tooltip[edit_rules_b;Opens larger text field for Rules set B]"..
	"field[0.2,-0.5;11,10;rules_c;Rules set C;"..s(fields.rules_c).."]"..
	"button[11,3.2;1,1;edit_rules_c;+]"..
	"tooltip[edit_rules_c;Opens larger text field for Rules set C]"..
	"field[0.2,0.5;11,10;rules_d;Rules set D;"..s(fields.rules_d).."]"..
	"button[11,4.2;1,1;edit_rules_d;+]"..
	"tooltip[edit_rules_d;Opens larger text field for Rules set D]"..

	"field[0.2,1.5;3,10;trunk;Trunk node name;"..s(fields.trunk).."]"..
	"field[3.2,1.5;3,10;leaves;Leaves node name;"..s(fields.leaves).."]"..
	"field[6.2,1.5;3,10;leaves2;Secondary leaves node name;"..s(fields.leaves2).."]"..
	"field[9.2,1.5;3,10;fruit;Fruit node name;"..s(fields.fruit).."]"..

	"field[0.2,2.5;3,10;trunk_type;Trunk type (single/double/crossed);"..s(fields.trunk_type).."]"..
	"tooltip[trunk_type;This field specifies the shape of the tree trunk. Possible values:\n- \"single\": trunk of size 1×1\n- \"double\": trunk of size 2×2\n- \"crossed\": trunk in cross shape (3×3).]"..
	"field[3.2,2.5;3,10;thin_branches;Thin branches? (true/false);"..s(fields.thin_branches).."]"..
	"tooltip[thin_branches;\"true\": All branches are just 1 node wide. \"false\": Branches can be larger.]"..
	"field[6.2,2.5;3,10;leaves2_chance;Secondary leaves chance (in percent);"..s(fields.leaves2_chance).."]"..
	"tooltip[leaves2_chance;Chance (in percent) to replace a leaves node by a secondary leaves node]"..
	"field[9.2,2.5;3,10;fruit_chance;Fruit chance (in percent);"..s(fields.fruit_chance).."]"..
	"tooltip[fruit_chance;Change (in percent) to replace a leaves node by a fruit node.]"..

	"field[0.2,3.5;3,10;iterations;Iterations;"..s(fields.iterations).."]"..
	"tooltip[iterations;Maximum number of iterations, usually between 2 and 5.]"..
	"field[3.2,3.5;3,10;random_level;Randomness level;"..s(fields.random_level).."]"..
	"tooltip[random_level;Factor to lower number of iterations, usually between 0 and 3.]"..
	"field[6.2,3.5;3,10;angle;Angle (in degrees);"..s(fields.angle).."]"..
	"field[9.2,3.5;3,10;name;Name;"..s(fields.name).."]"..
	"tooltip[name;An unique name for this tree, only used for convenience.]"..

	"button[3.5,8.5;3,1;edit_save;Save tree to database]"..
	"button[6.5,8.5;3,1;edit_clear;Clear fields]"
As you can see, the Y coordinates of buttons and fields are very different but they appear in kinda the same height. I have not yet managed to align buttons and fields perfectly.

So can anyone please give me an explanation of the formspec coordinate system and how it works now, especially with regards to fields vs buttons? Also, are there even more coordinates for other formspec elements?

Note this is not a support request for that particular mod but a general question since getting formspec coordinates right is pretty important.

User avatar
everamzah
Member
Posts: 490
Joined: Thu Jan 29, 2015 00:47
GitHub: everamzah
IRC: everamzah
In-game: everamzah

Re: How do formspec coordinates work?

by everamzah » Post

This isn't a solution but my personal experience: Take a screenshot and quit minetest, load the picture up and nudge the formspec buttons by small values. Go back into minetest, load the formspec and take another picture. Keep the picture up so you can look at it while you adjust the numbers.

I have no idea why they don't align, but lua_api.txt does mention that some elements use inventory sizes for X, Y.

User avatar
rubenwardy
Moderator
Posts: 6972
Joined: Tue Jun 12, 2012 18:11
GitHub: rubenwardy
IRC: rubenwardy
In-game: rubenwardy
Location: Bristol, United Kingdom
Contact:

Re: How do formspec coordinates work?

by rubenwardy » Post

It's witchcraft and black magic
Renewed Tab (my browser add-on) | Donate | Mods | Minetest Modding Book

Hello profile reader

Dragonop
Member
Posts: 1233
Joined: Tue Oct 23, 2012 12:59
GitHub: Dragonop
IRC: Dragonop
In-game: Dragonop
Location: Argentina

Re: How do formspec coordinates work?

by Dragonop » Post

Test and error, after a while you get used to it and "know" the dimensions and somehow where it will end up. Try lowering everything else instead of the buttons, and that might work, heh.
Can't say I know what I'm talking about, formspecs are hell for me.

User avatar
addi
Member
Posts: 666
Joined: Thu Sep 20, 2012 03:16
GitHub: adrido
Location: Black-Forest, Germany

Re: How do formspec coordinates work?

by addi » Post

yeah formspecs are realy magic! But there are 2 "magic" numbers that might help:
0 and -0.3

The 0 (zero) is needed for the elements heights (4th number):

Code: Select all

"field[0.2,-3.5;11,0;axiom;Axiom;"..s(fields.axiom).."]"..
   "button[11,0.2;1,0;edit_axiom;+]"..
Set the last coordinates always to 0 this makes handling easier.
the -0.3 is needed for the buttons then.
Example if your field starts at (0.2, 1) make the button start -0.3 above. E.g. (0.2, 1-0.3) = (0.2, 0.7)
Finished aligned code:

Code: Select all

     return ""..
    "field[0.2,1;11,0;axiom;Axiom;"..s(fields.axiom).."]"..
    "button[11,0.7;1,0;edit_axiom;+]"..
    "tooltip[edit_axiom;Opens larger text field for Axiom]"..
    "field[0.2,2;11,0;rules_a;Rules set A;"..s(fields.rules_a).."]"..
    "button[11,1.7;1,0;edit_rules_a;+]"..
    "tooltip[edit_rules_a;Opens larger text field for Rules set A]"..
    "field[0.2,3;11,0;rules_b;Rules set B;"..s(fields.rules_b).."]"..
    "button[11,2.7;1,0;edit_rules_b;+]"..
    "tooltip[edit_rules_b;Opens larger text field for Rules set B]"..
    "field[0.2,4;11,0;rules_c;Rules set C;"..s(fields.rules_c).."]"..
    "button[11,3.7;1,0;edit_rules_c;+]"..
    "tooltip[edit_rules_c;Opens larger text field for Rules set C]"..
    "field[0.2,5;11,0;rules_d;Rules set D;"..s(fields.rules_d).."]"..
    "button[11,4.7;1,0;edit_rules_d;+]"..
    "tooltip[edit_rules_d;Opens larger text field for Rules set D]"..

    "field[0.2,6;3,0;trunk;Trunk node name;"..s(fields.trunk).."]"..
    "field[3.2,6;3,0;leaves;Leaves node name;"..s(fields.leaves).."]"..
    "field[6.2,6;3,0;leaves2;Secondary leaves node name;"..s(fields.leaves2).."]"..
    "field[9.2,6;3,0;fruit;Fruit node name;"..s(fields.fruit).."]"..

    "field[0.2,7;3,0;trunk_type;Trunk type (single/double/crossed);"..s(fields.trunk_type).."]"..
    "tooltip[trunk_type;This field specifies the shape of the tree trunk. Possible values:\n- \"single\": trunk of size 1×1\n- \"double\": trunk of size 2×2\n- \"crossed\": trunk in cross shape (3×3).]"..
    "field[3.2,7;3,0;thin_branches;Thin branches? (true/false);"..s(fields.thin_branches).."]"..
    "tooltip[thin_branches;\"true\": All branches are just 1 node wide. \"false\": Branches can be larger.]"..
    "field[6.2,7;3,0;leaves2_chance;Secondary leaves chance (in percent);"..s(fields.leaves2_chance).."]"..
    "tooltip[leaves2_chance;Chance (in percent) to replace a leaves node by a secondary leaves node]"..
    "field[9.2,7;3,0;fruit_chance;Fruit chance (in percent);"..s(fields.fruit_chance).."]"..
    "tooltip[fruit_chance;Change (in percent) to replace a leaves node by a fruit node.]"..

    "field[0.2,8;3,0;iterations;Iterations;"..s(fields.iterations).."]"..
    "tooltip[iterations;Maximum number of iterations, usually between 2 and 5.]"..
    "field[3.2,8;3,0;random_level;Randomness level;"..s(fields.random_level).."]"..
    "tooltip[random_level;Factor to lower number of iterations, usually between 0 and 3.]"..
    "field[6.2,8;3,0;angle;Angle (in degrees);"..s(fields.angle).."]"..
    "field[9.2,8;3,0;name;Name;"..s(fields.name).."]"..
    "tooltip[name;An unique name for this tree, only used for convenience.]"..

    "button[3.5,8.7;3,0;edit_save;Save tree to database]"..
    "button[6.5,8.7;3,0;edit_clear;Clear fields]" 

User avatar
Wuzzy
Member
Posts: 4786
Joined: Mon Sep 24, 2012 15:01
GitHub: Wuzzy2
IRC: Wuzzy
In-game: Wuzzy
Contact:

Re: How do formspec coordinates work?

by Wuzzy » Post

Thanks, addi, it really works, I am surprised! But this begs the question: What the fuck?
Those numbers don't make any sense. Why are buttons offset by 0.3? Why do I have to set the height to 0?

Also, why is nothing of this documented?

User avatar
oleastre
Member
Posts: 81
Joined: Wed Aug 13, 2014 21:39
GitHub: oleastre
In-game: oleastre

Re: How do formspec coordinates work?

by oleastre » Post

I just had quick look at the code.
If I'm not mislead, the formspec is a simple layer around irrlicht ui elements that does some automatic scaling.
So, the number are not fixed on an easy grid, but rather raw elements sizes and positions as it is defined in the gui toolkit.
Maybe lack of documentation can be solved with a simple formspec generator (could be done as an inkscape plugin for example)

User avatar
addi
Member
Posts: 666
Joined: Thu Sep 20, 2012 03:16
GitHub: adrido
Location: Black-Forest, Germany

Re: How do formspec coordinates work?

by addi » Post

Wuzzy wrote:Thanks, addi, it really works, I am surprised! But this begs the question: What the fuck?
Those numbers don't make any sense. Why are buttons offset by 0.3? Why do I have to set the height to 0?

Also, why is nothing of this documented?
This is why I called it "magic" :-)

As far I could find out, the height is something special, if you place some elements with height they getting an offset.
have a look at this screen shot:
Image
I does not understand why it have such a behaviour. but as you see some elements have to be adjusted about 0.2 some about 0.3 and some does fit the grid

if someone thinks its usefull:

here ist the "grid" code:

Code: Select all

box[0,0;1,1;#FFFFFF]box[2,0;1,1;#FFFFFF]box[4,0;1,1;#FFFFFF]box[6,0;1,1;#FFFFFF]box[8,0;1,1;#FFFFFF]box[10,0;1,1;#FFFFFF]
box[1,1;1,1;#FFFFFF]box[3,1;1,1;#FFFFFF]box[5,1;1,1;#FFFFFF]box[7,1;1,1;#FFFFFF]box[9,1;1,1;#FFFFFF]
box[0,2;1,1;#FFFFFF]box[2,2;1,1;#FFFFFF]box[4,2;1,1;#FFFFFF]box[6,2;1,1;#FFFFFF]box[8,2;1,1;#FFFFFF]box[10,2;1,1;#FFFFFF]
box[1,3;1,1;#FFFFFF]box[3,3;1,1;#FFFFFF]box[5,3;1,1;#FFFFFF]box[7,3;1,1;#FFFFFF]box[9,3;1,1;#FFFFFF]
box[0,4;1,1;#FFFFFF]box[2,4;1,1;#FFFFFF]box[4,4;1,1;#FFFFFF]box[6,4;1,1;#FFFFFF]box[8,4;1,1;#FFFFFF]box[10,4;1,1;#FFFFFF]
box[1,5;1,1;#FFFFFF]box[3,5;1,1;#FFFFFF]box[5,5;1,1;#FFFFFF]box[7,5;1,1;#FFFFFF]box[9,5;1,1;#FFFFFF]
box[0,6;1,1;#FFFFFF]box[2,6;1,1;#FFFFFF]box[4,6;1,1;#FFFFFF]box[6,6;1,1;#FFFFFF]box[8,6;1,1;#FFFFFF]box[10,6;1,1;#FFFFFF]
box[1,7;1,1;#FFFFFF]box[3,7;1,1;#FFFFFF]box[5,7;1,1;#FFFFFF]box[7,7;1,1;#FFFFFF]box[9,7;1,1;#FFFFFF]
box[0,8;1,1;#FFFFFF]box[2,8;1,1;#FFFFFF]box[4,8;1,1;#FFFFFF]box[6,8;1,1;#FFFFFF]box[8,8;1,1;#FFFFFF]box[10,8;1,1;#FFFFFF]
box[1,9;1,1;#FFFFFF]box[3,9;1,1;#FFFFFF]box[5,9;1,1;#FFFFFF]box[7,9;1,1;#FFFFFF]box[9,9;1,1;#FFFFFF]
This helps pretty much if you want to find out the offsets.

Here is the code used in the screeshot:

Code: Select all

size[10,10]
field[0,1;4,0;random_level;Field 0,1 height 0;]
field[4,1;4,1;random_level;Field 4,1 height 1;]
button[0,2;4,0;random_level;Button 0,1 height 0]
button[4,2;4,1;random_level;Button 4,1 height 1]
textarea[0,3;4,0;name;Textarea 0,3 height 0;]
textarea[4,3;4,1;name;Textarea 4,3 height 1;]
dropdown[0,4;4,0;name;dropdown 0/4 height 0,item2,item3...;1]
dropdown[4,4;4,1;name;dropdown 0/4 height 1,item2,item3...;1]
list[current_player;main;0,5;4,0;List (0/5) height 0]
list[current_player;main;4,5;4,1;List (0/5) height 1]
box[0,0;1,1;#FFFFFF]box[2,0;1,1;#FFFFFF]box[4,0;1,1;#FFFFFF]box[6,0;1,1;#FFFFFF]box[8,0;1,1;#FFFFFF]box[10,0;1,1;#FFFFFF]
box[1,1;1,1;#FFFFFF]box[3,1;1,1;#FFFFFF]box[5,1;1,1;#FFFFFF]box[7,1;1,1;#FFFFFF]box[9,1;1,1;#FFFFFF]
box[0,2;1,1;#FFFFFF]box[2,2;1,1;#FFFFFF]box[4,2;1,1;#FFFFFF]box[6,2;1,1;#FFFFFF]box[8,2;1,1;#FFFFFF]box[10,2;1,1;#FFFFFF]
box[1,3;1,1;#FFFFFF]box[3,3;1,1;#FFFFFF]box[5,3;1,1;#FFFFFF]box[7,3;1,1;#FFFFFF]box[9,3;1,1;#FFFFFF]
box[0,4;1,1;#FFFFFF]box[2,4;1,1;#FFFFFF]box[4,4;1,1;#FFFFFF]box[6,4;1,1;#FFFFFF]box[8,4;1,1;#FFFFFF]box[10,4;1,1;#FFFFFF]
box[1,5;1,1;#FFFFFF]box[3,5;1,1;#FFFFFF]box[5,5;1,1;#FFFFFF]box[7,5;1,1;#FFFFFF]box[9,5;1,1;#FFFFFF]
box[0,6;1,1;#FFFFFF]box[2,6;1,1;#FFFFFF]box[4,6;1,1;#FFFFFF]box[6,6;1,1;#FFFFFF]box[8,6;1,1;#FFFFFF]box[10,6;1,1;#FFFFFF]
box[1,7;1,1;#FFFFFF]box[3,7;1,1;#FFFFFF]box[5,7;1,1;#FFFFFF]box[7,7;1,1;#FFFFFF]box[9,7;1,1;#FFFFFF]
box[0,8;1,1;#FFFFFF]box[2,8;1,1;#FFFFFF]box[4,8;1,1;#FFFFFF]box[6,8;1,1;#FFFFFF]box[8,8;1,1;#FFFFFF]box[10,8;1,1;#FFFFFF]
box[1,9;1,1;#FFFFFF]box[3,9;1,1;#FFFFFF]box[5,9;1,1;#FFFFFF]box[7,9;1,1;#FFFFFF]box[9,9;1,1;#FFFFFF]
oleastre wrote:I just had quick look at the code.
If I'm not mislead, the formspec is a simple layer around irrlicht ui elements that does some automatic scaling.
So, the number are not fixed on an easy grid, but rather raw elements sizes and positions as it is defined in the gui toolkit.
Maybe lack of documentation can be solved with a simple formspec generator (could be done as an inkscape plugin for example)
If someone could write such a plug-in it would be great, But in my opinion the whole formspec stuff needs to be rewritten.
Attachments
odd_offsets.PNG
odd_offsets.PNG (355.52 KiB) Viewed 430 times

User avatar
Wuzzy
Member
Posts: 4786
Joined: Mon Sep 24, 2012 15:01
GitHub: Wuzzy2
IRC: Wuzzy
In-game: Wuzzy
Contact:

Re: How do formspec coordinates work?

by Wuzzy » Post

But in my opinion the whole formspec stuff needs to be rewritten.
Yes, I fully agree. I don't care if this might break compability with existing formspecs, compability was broken quite a few times in the past anyways, so modders should expect this. A consistent formspec API is more important.
Writing some tools would be a nice-to-have, but they are no excuse for a poor API.

I am still baffled about the fact with the height 0 thing. Out of curiosity, what if I need to set the height explicitly? Then I can't use height 0.

User avatar
kaadmy
Member
Posts: 706
Joined: Thu Aug 27, 2015 23:07
GitHub: kaadmy
IRC: KaadmY
In-game: KaadmY kaadmy NeD

Re: How do formspec coordinates work?

by kaadmy » Post

@Wuzzy: try increasing the size coordinates by this: https://github.com/minetest/minetest/bl ... .cpp#L1987
Never paint white stripes on roads near Zebra crossings.

Pixture

twoelk
Member
Posts: 1482
Joined: Fri Apr 19, 2013 16:19
GitHub: twoelk
IRC: twoelk
In-game: twoelk
Location: northern Germany

Re: How do formspec coordinates work?

by twoelk » Post

I remember well when Sapier rewrote the formspec code in its current form and was pretty frustrated with the system he had to use. He questioned several times wether all the work he invested was really worth it or wether not some other system should be used. He asked many times for help but except for suggestions as to how the things should look ingame nobody came up with more than a vague idea of how to code it differently. There are other games and applications based on Irrlicht, how do they do it? Do they have easier to use systems? Do they use some better libraries for rendering the GUI?

In the spoiler you will find some code and pics of my latest battles with formspec
Spoiler
For my Roman Map I wanted to decorate the wiki mod a little by adding fancy borders. I soon gave up on the complicated ideas I first tried to implement and settled to simply use three small images of 5 by 5 pixels. One for the corners and one each for the vertical and the horizontal borders.

Image

Positioning was a long day of trail and error as I constantly had to restart the map to see the results and it took me some time to accept that there was no logic I could understand.

The relevant code I ended up with may be studied below:

Code: Select all

	return ("size[16,10]"
		.. "image[-0.1,10.15;20.11,0.3;border_h.png]"
		.. "image[-0.1,-0.3;20.11,0.3;border_h.png]"
		.. "image[-0.3,-0.1;0.3,12;border_v.png]"
		.. "image[15.85-0.3,-0.1;0.3,12;border_v.png]"
		.. "image[-0.3,-0.3;0.3,0.3;border_corner.png]"
		.. "image[15.85,-0.3;0.3,0.3;border_corner.png]"
		.. "image[-0.3,10.15;0.3,0.3;border_corner.png]"
		.. "image[15.85,10.15;0.3,0.3;border_corner.png]"
		.. "label[-0.1,0;Page]"
		.. "field[1.5,0.1;13,1;page;;"..esc(name).."]"
		.. "button[14,0;1,0.5;go;Go]"
		.. "button_exit[15,0;1,0.5;close;X]"
		.. "textarea[0.2,1.1;12,9;text;"..esc(name)..";"..esc(text).."]"
		.. buttons
		.. toolbar
	)
As you may notice the formspec has a size of 16 wide by 10 high, pretty much most of the screen.
Positioning reveals the allready known offset by -0.3.

The values for stretching the middle border sections are beyond me. Take note that the corners have a dimension of 0.3 by 0.3 so to get a width of 16-0.6=15.4, I actually have to use 20.11 and for the hight between corners of 10-0.6=9.4 I end up with 12!

It lines up astonishing well as may be obseved below. Nevermind the other elements such as textareas labels and buttons, I haven't fixed and adjusted those yet.

Image

The images are rendered according to the screen resolution so the width of each line differs a little although they should all be the same as each line is one pixel wide in the original image. A little strange is the black line that can be observed between the top right corner and the top border in the default resolution of 800x600
Image
I would really rather calculate exact values than having to use these numbers aquired by experimenting that just might fit somehow.
So yeah the current formspec system is difficult to handle but until somebody comes up with some better working code we are stuck with it and just like all others I wish somebody else than me would start documenting it for dummies.
Attachments
borders at 800x600
borders at 800x600
wiki_with_borders_in_800x600.png (151.16 KiB) Viewed 432 times
borders in fullscreen
borders in fullscreen
wiki_with_borders_in_fullscreen.png (150.35 KiB) Viewed 431 times
creating a border image
creating a border image
Image_in_mtPaint.png (22.51 KiB) Viewed 430 times

Sokomine
Member
Posts: 4276
Joined: Sun Sep 09, 2012 17:31
GitHub: Sokomine
IRC: Sokomine
In-game: Sokomine

Re: How do formspec coordinates work?

by Sokomine » Post

Oh yes, formspecs. Arranging them so that they look halfway acceptable is very tricky. One of the things I fight with most is the placement of text. Buttons and input fields usually work more or less fine after some experimentation, but longer texts are hard to get well done. Something similar to HTML would be nice. Sadly, that's far too complicated and does rely on a lot of additional factors as well.
A list of my mods can be found here.

Post Reply

Who is online

Users browsing this forum: No registered users and 5 guests