guiFormspecMenu: Allow fraction values for container[] (#7497)
authorSmallJoker <SmallJoker@users.noreply.github.com>
Sat, 4 Aug 2018 16:55:54 +0000 (18:55 +0200)
committerGitHub <noreply@github.com>
Sat, 4 Aug 2018 16:55:54 +0000 (18:55 +0200)
Switch spacing and pos_offset to v2f32 for percision, add helper function

src/gui/guiFormSpecMenu.cpp
src/gui/guiFormSpecMenu.h

index 82210c5916aa36803a3caaef11c57b80f617d44a..9656af3a7381d261e3d12b7d1b98d8c5f4a1175a 100644 (file)
@@ -258,6 +258,21 @@ std::vector<std::string>* GUIFormSpecMenu::getDropDownValues(const std::string &
        return NULL;
 }
 
+v2s32 GUIFormSpecMenu::getElementBasePos(bool absolute,
+               const std::vector<std::string> *v_pos)
+{
+       v2s32 pos = padding;
+       if (absolute)
+               pos += AbsoluteRect.UpperLeftCorner;
+
+       v2f32 pos_f = v2f32(pos.X, pos.Y) + pos_offset * spacing;
+       if (v_pos) {
+               pos_f.X += stof((*v_pos)[0]) * spacing.X;
+               pos_f.Y += stof((*v_pos)[1]) * spacing.Y;
+       }
+       return v2s32(pos_f.X, pos_f.Y);
+}
+
 void GUIFormSpecMenu::parseSize(parserData* data, const std::string &element)
 {
        std::vector<std::string> parts = split(element,',');
@@ -340,10 +355,7 @@ void GUIFormSpecMenu::parseList(parserData* data, const std::string &element)
                else
                        loc.deSerialize(location);
 
-               v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
-               pos.X += stof(v_pos[0]) * (float)spacing.X;
-               pos.Y += stof(v_pos[1]) * (float)spacing.Y;
-
+               v2s32 pos = getElementBasePos(true, &v_pos);
                v2s32 geom;
                geom.X = stoi(v_geom[0]);
                geom.Y = stoi(v_geom[1]);
@@ -420,9 +432,7 @@ void GUIFormSpecMenu::parseCheckbox(parserData* data, const std::string &element
 
                MY_CHECKPOS("checkbox",0);
 
-               v2s32 pos = padding + pos_offset * spacing;
-               pos.X += stof(v_pos[0]) * (float) spacing.X;
-               pos.Y += stof(v_pos[1]) * (float) spacing.Y;
+               v2s32 pos = getElementBasePos(false, &v_pos);
 
                bool fselected = false;
 
@@ -471,9 +481,7 @@ void GUIFormSpecMenu::parseScrollBar(parserData* data, const std::string &elemen
 
                MY_CHECKPOS("scrollbar",0);
 
-               v2s32 pos = padding + pos_offset * spacing;
-               pos.X += stof(v_pos[0]) * (float) spacing.X;
-               pos.Y += stof(v_pos[1]) * (float) spacing.Y;
+               v2s32 pos = getElementBasePos(false, &v_pos);
 
                if (v_dim.size() != 2) {
                        errorstream<< "Invalid size for element " << "scrollbar"
@@ -482,8 +490,8 @@ void GUIFormSpecMenu::parseScrollBar(parserData* data, const std::string &elemen
                }
 
                v2s32 dim;
-               dim.X = stof(v_dim[0]) * (float) spacing.X;
-               dim.Y = stof(v_dim[1]) * (float) spacing.Y;
+               dim.X = stof(v_dim[0]) * spacing.X;
+               dim.Y = stof(v_dim[1]) * spacing.Y;
 
                core::rect<s32> rect =
                                core::rect<s32>(pos.X, pos.Y, pos.X + dim.X, pos.Y + dim.Y);
@@ -532,10 +540,7 @@ void GUIFormSpecMenu::parseImage(parserData* data, const std::string &element)
                MY_CHECKPOS("image", 0);
                MY_CHECKGEOM("image", 1);
 
-               v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
-               pos.X += stof(v_pos[0]) * (float) spacing.X;
-               pos.Y += stof(v_pos[1]) * (float) spacing.Y;
-
+               v2s32 pos = getElementBasePos(true, &v_pos);
                v2s32 geom;
                geom.X = stof(v_geom[0]) * (float)imgsize.X;
                geom.Y = stof(v_geom[1]) * (float)imgsize.Y;
@@ -552,9 +557,7 @@ void GUIFormSpecMenu::parseImage(parserData* data, const std::string &element)
 
                MY_CHECKPOS("image", 0);
 
-               v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
-               pos.X += stof(v_pos[0]) * (float) spacing.X;
-               pos.Y += stof(v_pos[1]) * (float) spacing.Y;
+               v2s32 pos = getElementBasePos(true, &v_pos);
 
                if (!data->explicit_size)
                        warningstream<<"invalid use of image without a size[] element"<<std::endl;
@@ -578,10 +581,7 @@ void GUIFormSpecMenu::parseItemImage(parserData* data, const std::string &elemen
                MY_CHECKPOS("itemimage",0);
                MY_CHECKGEOM("itemimage",1);
 
-               v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
-               pos.X += stof(v_pos[0]) * (float) spacing.X;
-               pos.Y += stof(v_pos[1]) * (float) spacing.Y;
-
+               v2s32 pos = getElementBasePos(true, &v_pos);
                v2s32 geom;
                geom.X = stof(v_geom[0]) * (float)imgsize.X;
                geom.Y = stof(v_geom[1]) * (float)imgsize.Y;
@@ -610,12 +610,9 @@ void GUIFormSpecMenu::parseButton(parserData* data, const std::string &element,
                MY_CHECKPOS("button",0);
                MY_CHECKGEOM("button",1);
 
-               v2s32 pos = padding + pos_offset * spacing;
-               pos.X += stof(v_pos[0]) * (float)spacing.X;
-               pos.Y += stof(v_pos[1]) * (float)spacing.Y;
-
+               v2s32 pos = getElementBasePos(false, &v_pos);
                v2s32 geom;
-               geom.X = (stof(v_geom[0]) * (float)spacing.X)-(spacing.X-imgsize.X);
+               geom.X = (stof(v_geom[0]) * spacing.X) - (spacing.X - imgsize.X);
                pos.Y += (stof(v_geom[1]) * (float)imgsize.Y)/2;
 
                core::rect<s32> rect =
@@ -663,13 +660,13 @@ void GUIFormSpecMenu::parseBackground(parserData* data, const std::string &eleme
                MY_CHECKPOS("background",0);
                MY_CHECKGEOM("background",1);
 
-               v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
-               pos.X += stof(v_pos[0]) * (float)spacing.X - ((float)spacing.X - (float)imgsize.X)/2;
-               pos.Y += stof(v_pos[1]) * (float)spacing.Y - ((float)spacing.Y - (float)imgsize.Y)/2;
+               v2s32 pos = getElementBasePos(true, &v_pos);
+               pos.X -= (spacing.X - (float)imgsize.X) / 2;
+               pos.Y -= (spacing.Y - (float)imgsize.Y) / 2;
 
                v2s32 geom;
-               geom.X = stof(v_geom[0]) * (float)spacing.X;
-               geom.Y = stof(v_geom[1]) * (float)spacing.Y;
+               geom.X = stof(v_geom[0]) * spacing.X;
+               geom.Y = stof(v_geom[1]) * spacing.Y;
 
                if (!data->explicit_size)
                        warningstream<<"invalid use of background without a size[] element"<<std::endl;
@@ -739,13 +736,10 @@ void GUIFormSpecMenu::parseTable(parserData* data, const std::string &element)
                MY_CHECKPOS("table",0);
                MY_CHECKGEOM("table",1);
 
-               v2s32 pos = padding + pos_offset * spacing;
-               pos.X += stof(v_pos[0]) * (float)spacing.X;
-               pos.Y += stof(v_pos[1]) * (float)spacing.Y;
-
+               v2s32 pos = getElementBasePos(false, &v_pos);
                v2s32 geom;
-               geom.X = stof(v_geom[0]) * (float)spacing.X;
-               geom.Y = stof(v_geom[1]) * (float)spacing.Y;
+               geom.X = stof(v_geom[0]) * spacing.X;
+               geom.Y = stof(v_geom[1]) * spacing.Y;
 
                core::rect<s32> rect = core::rect<s32>(pos.X, pos.Y, pos.X+geom.X, pos.Y+geom.Y);
 
@@ -809,13 +803,10 @@ void GUIFormSpecMenu::parseTextList(parserData* data, const std::string &element
                MY_CHECKPOS("textlist",0);
                MY_CHECKGEOM("textlist",1);
 
-               v2s32 pos = padding + pos_offset * spacing;
-               pos.X += stof(v_pos[0]) * (float)spacing.X;
-               pos.Y += stof(v_pos[1]) * (float)spacing.Y;
-
+               v2s32 pos = getElementBasePos(false, &v_pos);
                v2s32 geom;
-               geom.X = stof(v_geom[0]) * (float)spacing.X;
-               geom.Y = stof(v_geom[1]) * (float)spacing.Y;
+               geom.X = stof(v_geom[0]) * spacing.X;
+               geom.Y = stof(v_geom[1]) * spacing.Y;
 
 
                core::rect<s32> rect = core::rect<s32>(pos.X, pos.Y, pos.X+geom.X, pos.Y+geom.Y);
@@ -873,11 +864,9 @@ void GUIFormSpecMenu::parseDropDown(parserData* data, const std::string &element
 
                MY_CHECKPOS("dropdown",0);
 
-               v2s32 pos = padding + pos_offset * spacing;
-               pos.X += stof(v_pos[0]) * (float)spacing.X;
-               pos.Y += stof(v_pos[1]) * (float)spacing.Y;
+               v2s32 pos = getElementBasePos(false, &v_pos);
 
-               s32 width = stof(parts[1]) * (float)spacing.Y;
+               s32 width = stof(parts[1]) * spacing.Y;
 
                core::rect<s32> rect = core::rect<s32>(pos.X, pos.Y,
                                pos.X + width, pos.Y + (m_btn_height * 2));
@@ -945,12 +934,11 @@ void GUIFormSpecMenu::parsePwdField(parserData* data, const std::string &element
                MY_CHECKPOS("pwdfield",0);
                MY_CHECKGEOM("pwdfield",1);
 
-               v2s32 pos = pos_offset * spacing;
-               pos.X += stof(v_pos[0]) * (float)spacing.X;
-               pos.Y += stof(v_pos[1]) * (float)spacing.Y;
+               v2s32 pos = getElementBasePos(false, &v_pos);
+               pos -= padding;
 
                v2s32 geom;
-               geom.X = (stof(v_geom[0]) * (float)spacing.X)-(spacing.X-imgsize.X);
+               geom.X = (stof(v_geom[0]) * spacing.X) - (spacing.X - imgsize.X);
 
                pos.Y += (stof(v_geom[1]) * (float)imgsize.Y)/2;
                pos.Y -= m_btn_height;
@@ -1083,7 +1071,7 @@ void GUIFormSpecMenu::parseSimpleField(parserData* data,
        if(data->explicit_size)
                warningstream<<"invalid use of unpositioned \"field\" in inventory"<<std::endl;
 
-       v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
+       v2s32 pos = getElementBasePos(false, nullptr);
        pos.Y = ((m_fields.size()+2)*60);
        v2s32 size = DesiredRect.getSize();
 
@@ -1129,13 +1117,12 @@ void GUIFormSpecMenu::parseTextArea(parserData* data, std::vector<std::string>&
        MY_CHECKPOS(type,0);
        MY_CHECKGEOM(type,1);
 
-       v2s32 pos = pos_offset * spacing;
-       pos.X += stof(v_pos[0]) * (float) spacing.X;
-       pos.Y += stof(v_pos[1]) * (float) spacing.Y;
+       v2s32 pos = getElementBasePos(false, &v_pos);
+       pos -= padding;
 
        v2s32 geom;
 
-       geom.X = (stof(v_geom[0]) * (float)spacing.X)-(spacing.X-imgsize.X);
+       geom.X = (stof(v_geom[0]) * spacing.X) - (spacing.X - imgsize.X);
 
        if (type == "textarea")
        {
@@ -1210,9 +1197,9 @@ void GUIFormSpecMenu::parseLabel(parserData* data, const std::string &element)
 
                MY_CHECKPOS("label",0);
 
-               v2s32 pos = padding + pos_offset * spacing;
-               pos.X += stof(v_pos[0]) * (float)spacing.X;
-               pos.Y += (stof(v_pos[1]) + 7.0/30.0) * (float)spacing.Y;
+               v2s32 pos = getElementBasePos(false, nullptr);
+               pos.X += stof(v_pos[0]) * spacing.X;
+               pos.Y += (stof(v_pos[1]) + 7.0f / 30.0f) * spacing.Y;
 
                if(!data->explicit_size)
                        warningstream<<"invalid use of label without a size[] element"<<std::endl;
@@ -1265,9 +1252,7 @@ void GUIFormSpecMenu::parseVertLabel(parserData* data, const std::string &elemen
 
                MY_CHECKPOS("vertlabel",1);
 
-               v2s32 pos = padding + pos_offset * spacing;
-               pos.X += stof(v_pos[0]) * (float)spacing.X;
-               pos.Y += stof(v_pos[1]) * (float)spacing.Y;
+               v2s32 pos = getElementBasePos(false, &v_pos);
 
                core::rect<s32> rect = core::rect<s32>(
                                pos.X, pos.Y+((imgsize.Y/2)- m_btn_height),
@@ -1319,12 +1304,10 @@ void GUIFormSpecMenu::parseImageButton(parserData* data, const std::string &elem
                MY_CHECKPOS("imagebutton",0);
                MY_CHECKGEOM("imagebutton",1);
 
-               v2s32 pos = padding + pos_offset * spacing;
-               pos.X += stof(v_pos[0]) * (float)spacing.X;
-               pos.Y += stof(v_pos[1]) * (float)spacing.Y;
+               v2s32 pos = getElementBasePos(false, &v_pos);
                v2s32 geom;
-               geom.X = (stof(v_geom[0]) * (float)spacing.X)-(spacing.X-imgsize.X);
-               geom.Y = (stof(v_geom[1]) * (float)spacing.Y)-(spacing.Y-imgsize.Y);
+               geom.X = (stof(v_geom[0]) * spacing.X) - (spacing.X - imgsize.X);
+               geom.Y = (stof(v_geom[1]) * spacing.Y) - (spacing.Y - imgsize.Y);
 
                bool noclip     = false;
                bool drawborder = true;
@@ -1424,9 +1407,13 @@ void GUIFormSpecMenu::parseTabHeader(parserData* data, const std::string &elemen
 
                spec.ftype = f_TabHeader;
 
-               v2s32 pos = pos_offset * spacing;
-               pos.X += stof(v_pos[0]) * (float)spacing.X;
-               pos.Y += stof(v_pos[1]) * (float)spacing.Y - m_btn_height * 2;
+               v2s32 pos;
+               {
+                       v2f32 pos_f = pos_offset * spacing;
+                       pos_f.X += stof(v_pos[0]) * spacing.X;
+                       pos_f.Y += stof(v_pos[1]) * spacing.Y - m_btn_height * 2;
+                       pos = v2s32(pos_f.X, pos_f.Y);
+               }
                v2s32 geom;
                geom.X = DesiredRect.getWidth();
                geom.Y = m_btn_height*2;
@@ -1489,12 +1476,10 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data, const std::string &
                MY_CHECKPOS("itemimagebutton",0);
                MY_CHECKGEOM("itemimagebutton",1);
 
-               v2s32 pos = padding + pos_offset * spacing;
-               pos.X += stof(v_pos[0]) * (float)spacing.X;
-               pos.Y += stof(v_pos[1]) * (float)spacing.Y;
+               v2s32 pos = getElementBasePos(false, &v_pos);
                v2s32 geom;
-               geom.X = (stof(v_geom[0]) * (float)spacing.X)-(spacing.X-imgsize.X);
-               geom.Y = (stof(v_geom[1]) * (float)spacing.Y)-(spacing.Y-imgsize.Y);
+               geom.X = (stof(v_geom[0]) * spacing.X) - (spacing.X - imgsize.X);
+               geom.Y = (stof(v_geom[1]) * spacing.Y) - (spacing.Y - imgsize.Y);
 
                core::rect<s32> rect = core::rect<s32>(pos.X, pos.Y, pos.X+geom.X, pos.Y+geom.Y);
 
@@ -1527,9 +1512,8 @@ void GUIFormSpecMenu::parseItemImageButton(parserData* data, const std::string &
                rect+=data->basepos-padding;
                spec.rect=rect;
                m_fields.push_back(spec);
-               pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
-               pos.X += stof(v_pos[0]) * (float) spacing.X;
-               pos.Y += stof(v_pos[1]) * (float) spacing.Y;
+
+               pos = getElementBasePos(true, &v_pos);
                m_itemimages.emplace_back("", item_name, e, pos, geom);
                m_static_texts.emplace_back(utf8_to_wide(label), rect, e);
                return;
@@ -1550,13 +1534,10 @@ void GUIFormSpecMenu::parseBox(parserData* data, const std::string &element)
                MY_CHECKPOS("box",0);
                MY_CHECKGEOM("box",1);
 
-               v2s32 pos = padding + AbsoluteRect.UpperLeftCorner + pos_offset * spacing;
-               pos.X += stof(v_pos[0]) * (float) spacing.X;
-               pos.Y += stof(v_pos[1]) * (float) spacing.Y;
-
+               v2s32 pos = getElementBasePos(true, &v_pos);
                v2s32 geom;
-               geom.X = stof(v_geom[0]) * (float)spacing.X;
-               geom.Y = stof(v_geom[1]) * (float)spacing.Y;
+               geom.X = stof(v_geom[0]) * spacing.X;
+               geom.Y = stof(v_geom[1]) * spacing.Y;
 
                video::SColor tmp_color;
 
@@ -2155,7 +2136,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
                // is 2/5 vertical inventory slot spacing, and button
                // half-height is 7/8 of font height.
                imgsize = v2s32(use_imgsize, use_imgsize);
-               spacing = v2s32(use_imgsize*5.0/4, use_imgsize*15.0/13);
+               spacing = v2f32(use_imgsize*5.0/4, use_imgsize*15.0/13);
                padding = v2s32(use_imgsize*3.0/8, use_imgsize*3.0/8);
                m_btn_height = use_imgsize*15.0/13 * 0.35;
 
@@ -2193,7 +2174,7 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
        gui::IGUIFont *old_font = skin->getFont();
        skin->setFont(m_font);
 
-       pos_offset = v2s32();
+       pos_offset = v2f32();
 
        if (enable_prepends) {
                std::vector<std::string> prepend_elements = split(m_formspec_prepend, ']');
index 013ba65cb08f6791aa476d951d39c0e9d9bfeefd..501b4db1b1da9ed5662865d1b04e7fc4e94797a9 100644 (file)
@@ -372,13 +372,15 @@ protected:
        {
                        return padding + offset + AbsoluteRect.UpperLeftCorner;
        }
+       v2s32 getElementBasePos(bool absolute,
+                       const std::vector<std::string> *v_pos);
 
        v2s32 padding;
-       v2s32 spacing;
+       v2f32 spacing;
        v2s32 imgsize;
        v2s32 offset;
-       v2s32 pos_offset;
-       std::stack<v2s32> container_stack;
+       v2f32 pos_offset;
+       std::stack<v2f32> container_stack;
 
        InventoryManager *m_invmgr;
        ISimpleTextureSource *m_tsrc;