forked from Mirrorlandia_minetest/minetest
FormSpec: Add position and anchor elements (#5284)
This commit is contained in:
parent
22df959343
commit
6de83a2756
@ -1522,6 +1522,16 @@ examples.
|
|||||||
* `fixed_size`: `true`/`false` (optional)
|
* `fixed_size`: `true`/`false` (optional)
|
||||||
* deprecated: `invsize[<W>,<H>;]`
|
* deprecated: `invsize[<W>,<H>;]`
|
||||||
|
|
||||||
|
#### `position[<X>,<Y>]`
|
||||||
|
* Define the position of the formspec
|
||||||
|
* A value between 0.0 and 1.0 represents a position inside the screen
|
||||||
|
* The default value is the center of the screen (0.5, 0.5)
|
||||||
|
|
||||||
|
#### `anchor[<X>,<Y>]`
|
||||||
|
* Define the anchor of the formspec
|
||||||
|
* A value between 0.0 and 1.0 represents an anchor inside the formspec
|
||||||
|
* The default value is the center of the formspec (0.5, 0.5)
|
||||||
|
|
||||||
#### `container[<X>,<Y>]`
|
#### `container[<X>,<Y>]`
|
||||||
* Start of a container block, moves all physical elements in the container by (X, Y)
|
* Start of a container block, moves all physical elements in the container by (X, Y)
|
||||||
* Must have matching container_end
|
* Must have matching container_end
|
||||||
|
@ -1706,6 +1706,74 @@ bool GUIFormSpecMenu::parseSizeDirect(parserData* data, std::string element)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool GUIFormSpecMenu::parsePositionDirect(parserData *data, const std::string &element)
|
||||||
|
{
|
||||||
|
if (element.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::vector<std::string> parts = split(element, '[');
|
||||||
|
|
||||||
|
if (parts.size() != 2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::string type = trim(parts[0]);
|
||||||
|
std::string description = trim(parts[1]);
|
||||||
|
|
||||||
|
if (type != "position")
|
||||||
|
return false;
|
||||||
|
|
||||||
|
parsePosition(data, description);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GUIFormSpecMenu::parsePosition(parserData *data, const std::string &element)
|
||||||
|
{
|
||||||
|
std::vector<std::string> parts = split(element, ',');
|
||||||
|
|
||||||
|
if (parts.size() == 2) {
|
||||||
|
data->offset.X = stof(parts[0]);
|
||||||
|
data->offset.Y = stof(parts[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
errorstream << "Invalid position element (" << parts.size() << "): '" << element << "'" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GUIFormSpecMenu::parseAnchorDirect(parserData *data, const std::string &element)
|
||||||
|
{
|
||||||
|
if (element.empty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::vector<std::string> parts = split(element, '[');
|
||||||
|
|
||||||
|
if (parts.size() != 2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::string type = trim(parts[0]);
|
||||||
|
std::string description = trim(parts[1]);
|
||||||
|
|
||||||
|
if (type != "anchor")
|
||||||
|
return false;
|
||||||
|
|
||||||
|
parseAnchor(data, description);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GUIFormSpecMenu::parseAnchor(parserData *data, const std::string &element)
|
||||||
|
{
|
||||||
|
std::vector<std::string> parts = split(element, ',');
|
||||||
|
|
||||||
|
if (parts.size() == 2) {
|
||||||
|
data->anchor.X = stof(parts[0]);
|
||||||
|
data->anchor.Y = stof(parts[1]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
errorstream << "Invalid anchor element (" << parts.size() << "): '" << element << "'" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
void GUIFormSpecMenu::parseElement(parserData* data, std::string element)
|
void GUIFormSpecMenu::parseElement(parserData* data, std::string element)
|
||||||
{
|
{
|
||||||
//some prechecks
|
//some prechecks
|
||||||
@ -1917,6 +1985,8 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
|
|||||||
|
|
||||||
mydata.size= v2s32(100,100);
|
mydata.size= v2s32(100,100);
|
||||||
mydata.screensize = screensize;
|
mydata.screensize = screensize;
|
||||||
|
mydata.offset = v2f32(0.5f, 0.5f);
|
||||||
|
mydata.anchor = v2f32(0.5f, 0.5f);
|
||||||
|
|
||||||
// Base position of contents of form
|
// Base position of contents of form
|
||||||
mydata.basepos = getBasePos();
|
mydata.basepos = getBasePos();
|
||||||
@ -1983,6 +2053,21 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* "position" element is always after "size" element if it used */
|
||||||
|
for (; i< elements.size(); i++) {
|
||||||
|
if (!parsePositionDirect(&mydata, elements[i])) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* "anchor" element is always after "position" (or "size" element) if it used */
|
||||||
|
for (; i< elements.size(); i++) {
|
||||||
|
if (!parseAnchorDirect(&mydata, elements[i])) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (mydata.explicit_size) {
|
if (mydata.explicit_size) {
|
||||||
// compute scaling for specified form size
|
// compute scaling for specified form size
|
||||||
if (m_lock) {
|
if (m_lock) {
|
||||||
@ -2066,10 +2151,10 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
|
|||||||
padding.Y*2+spacing.Y*(mydata.invsize.Y-1.0)+imgsize.Y + m_btn_height*2.0/3.0
|
padding.Y*2+spacing.Y*(mydata.invsize.Y-1.0)+imgsize.Y + m_btn_height*2.0/3.0
|
||||||
);
|
);
|
||||||
DesiredRect = mydata.rect = core::rect<s32>(
|
DesiredRect = mydata.rect = core::rect<s32>(
|
||||||
mydata.screensize.X/2 - mydata.size.X/2 + offset.X,
|
(s32)((f32)mydata.screensize.X * mydata.offset.X) - (s32)(mydata.anchor.X * (f32)mydata.size.X) + offset.X,
|
||||||
mydata.screensize.Y/2 - mydata.size.Y/2 + offset.Y,
|
(s32)((f32)mydata.screensize.Y * mydata.offset.Y) - (s32)(mydata.anchor.Y * (f32)mydata.size.Y) + offset.Y,
|
||||||
mydata.screensize.X/2 + mydata.size.X/2 + offset.X,
|
(s32)((f32)mydata.screensize.X * mydata.offset.X) + (s32)((1.0 - mydata.anchor.X) * (f32)mydata.size.X) + offset.X,
|
||||||
mydata.screensize.Y/2 + mydata.size.Y/2 + offset.Y
|
(s32)((f32)mydata.screensize.Y * mydata.offset.Y) + (s32)((1.0 - mydata.anchor.Y) * (f32)mydata.size.Y) + offset.Y
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
// Non-size[] form must consist only of text fields and
|
// Non-size[] form must consist only of text fields and
|
||||||
@ -2078,10 +2163,10 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
|
|||||||
m_font = g_fontengine->getFont();
|
m_font = g_fontengine->getFont();
|
||||||
m_btn_height = font_line_height(m_font) * 0.875;
|
m_btn_height = font_line_height(m_font) * 0.875;
|
||||||
DesiredRect = core::rect<s32>(
|
DesiredRect = core::rect<s32>(
|
||||||
mydata.screensize.X/2 - 580/2,
|
(s32)((f32)mydata.screensize.X * mydata.offset.X) - (s32)(mydata.anchor.X * 580.0),
|
||||||
mydata.screensize.Y/2 - 300/2,
|
(s32)((f32)mydata.screensize.Y * mydata.offset.Y) - (s32)(mydata.anchor.Y * 300.0),
|
||||||
mydata.screensize.X/2 + 580/2,
|
(s32)((f32)mydata.screensize.X * mydata.offset.X) + (s32)((1.0 - mydata.anchor.X) * 580.0),
|
||||||
mydata.screensize.Y/2 + 300/2
|
(s32)((f32)mydata.screensize.Y * mydata.offset.Y) + (s32)((1.0 - mydata.anchor.Y) * 300.0)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
recalculateAbsolutePosition(false);
|
recalculateAbsolutePosition(false);
|
||||||
|
@ -447,6 +447,8 @@ private:
|
|||||||
bool explicit_size;
|
bool explicit_size;
|
||||||
v2f invsize;
|
v2f invsize;
|
||||||
v2s32 size;
|
v2s32 size;
|
||||||
|
v2f32 offset;
|
||||||
|
v2f32 anchor;
|
||||||
core::rect<s32> rect;
|
core::rect<s32> rect;
|
||||||
v2s32 basepos;
|
v2s32 basepos;
|
||||||
v2u32 screensize;
|
v2u32 screensize;
|
||||||
@ -502,6 +504,10 @@ private:
|
|||||||
bool parseVersionDirect(std::string data);
|
bool parseVersionDirect(std::string data);
|
||||||
bool parseSizeDirect(parserData* data, std::string element);
|
bool parseSizeDirect(parserData* data, std::string element);
|
||||||
void parseScrollBar(parserData* data, std::string element);
|
void parseScrollBar(parserData* data, std::string element);
|
||||||
|
bool parsePositionDirect(parserData *data, const std::string &element);
|
||||||
|
void parsePosition(parserData *data, const std::string &element);
|
||||||
|
bool parseAnchorDirect(parserData *data, const std::string &element);
|
||||||
|
void parseAnchor(parserData *data, const std::string &element);
|
||||||
|
|
||||||
void tryClose();
|
void tryClose();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user