Backport (II): "FormSpec: 9-slice images, animated_images, and fgimg_middle (#12453)"

* FormSpec: 9-slice images and animated_images

* Add fgimg_middle; clean up code

* Address issues, add tests

* Fix stupid error; bump formspec version

* Re-add image[] elements without a size
master
Vincent Robinson 2022-07-03 05:52:26 -07:00 committed by Maksim
parent f09359eb58
commit 0bfc98fe26
3 changed files with 36 additions and 14 deletions

View File

@ -2288,7 +2288,8 @@ Elements
* Show an image.
* `middle` (optional): Makes the image render in 9-sliced mode and defines the middle rect.
Requires formspec version >= 4. See `background9[]` documentation for more information.
* Requires formspec version >= 4.
* See `background9[]` documentation for more information.
### `animated_image[<X>,<Y>;<W>,<H>;<name>;<texture name>;<frame count>;<frame duration>;<frame start>;<middle>]`
@ -2300,7 +2301,8 @@ Elements
* `frame duration`: Milliseconds between each frame. `0` means the frames don't advance.
* `frame start` (optional): The index of the frame to start on. Default `1`.
* `middle` (optional): Makes the image render in 9-sliced mode and defines the middle rect.
Requires formspec version >= 4. See `background9[]` documentation for more information.
* Requires formspec version >= 4.
* See `background9[]` documentation for more information.
### `model[<X>,<Y>;<W>,<H>;<name>;<mesh>;<textures>;<rotation X,Y>;<continuous>;<mouse control>;<frame loop range>]`

View File

@ -802,31 +802,51 @@ void GUIFormSpecMenu::parseImage(parserData* data, const std::string &element)
{
std::vector<std::string> parts = split(element,';');
if (parts.size() == 3 || parts.size() == 4 ||
if ((parts.size() >= 2 && parts.size() <= 4) ||
(parts.size() > 4 && m_formspec_version > FORMSPEC_API_VERSION))
{
std::vector<std::string> v_pos = split(parts[0],',');
std::vector<std::string> v_geom = split(parts[1],',');
std::string name = unescape_string(parts[2]);
size_t offset = parts.size() >= 3;
std::vector<std::string> v_pos = split(parts[0],',');
MY_CHECKPOS("image", 0);
MY_CHECKGEOM("image", 1);
std::vector<std::string> v_geom;
if (parts.size() >= 3) {
v_geom = split(parts[1],',');
MY_CHECKGEOM("image", 1);
}
std::string name = unescape_string(parts[1 + offset]);
video::ITexture *texture = m_tsrc->getTexture(name);
v2s32 pos;
v2s32 geom;
if (parts.size() < 3) {
if (texture != nullptr) {
core::dimension2du dim = texture->getOriginalSize();
geom.X = dim.Width;
geom.Y = dim.Height;
} else {
geom = v2s32(0);
}
}
if (data->real_coordinates) {
pos = getRealCoordinateBasePos(v_pos);
geom = getRealCoordinateGeometry(v_geom);
if (parts.size() >= 3)
geom = getRealCoordinateGeometry(v_geom);
} else {
pos = getElementBasePos(&v_pos);
geom.X = stof(v_geom[0]) * (float)imgsize.X;
geom.Y = stof(v_geom[1]) * (float)imgsize.Y;
if (parts.size() >= 3) {
geom.X = stof(v_geom[0]) * (float)imgsize.X;
geom.Y = stof(v_geom[1]) * (float)imgsize.Y;
}
}
if (!data->explicit_size)
warningstream << "Invalid use of image without a size[] element"
<< std::endl;
warningstream << "Invalid use of image without a size[] element" << std::endl;
FieldSpec spec(
name,
@ -845,7 +865,7 @@ void GUIFormSpecMenu::parseImage(parserData* data, const std::string &element)
GUIAnimatedImage *e = new GUIAnimatedImage(Environment, data->current_parent,
spec.fid, rect);
e->setTexture(m_tsrc->getTexture(name));
e->setTexture(texture);
e->setMiddleRect(middle);
auto style = getDefaultStyleForElement("image", spec.fname);

View File

@ -227,7 +227,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define PASSWORD_SIZE 28 // Maximum password length. Allows for
// base64-encoded SHA-1 (27+\0).
// See also: Formspec Version History in doc/lua_api.txt
// See also formspec [Version History] in doc/lua_api.txt
#define FORMSPEC_API_VERSION 4
#define TEXTURENAME_ALLOWED_CHARS "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_.-"