aboutsummaryrefslogtreecommitdiff
path: root/src/gui/guiFormSpecMenu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/guiFormSpecMenu.cpp')
-rw-r--r--src/gui/guiFormSpecMenu.cpp86
1 files changed, 86 insertions, 0 deletions
diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp
index 7e3ad3b15..039b28e79 100644
--- a/src/gui/guiFormSpecMenu.cpp
+++ b/src/gui/guiFormSpecMenu.cpp
@@ -65,6 +65,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "guiScrollContainer.h"
#include "intlGUIEditBox.h"
#include "guiHyperText.h"
+#include "guiScene.h"
#define MY_CHECKPOS(a,b) \
if (v_pos.size() != 2) { \
@@ -2695,6 +2696,86 @@ void GUIFormSpecMenu::parseSetFocus(const std::string &element)
<< "'" << std::endl;
}
+void GUIFormSpecMenu::parseModel(parserData *data, const std::string &element)
+{
+ std::vector<std::string> parts = split(element, ';');
+
+ if (parts.size() < 5 || (parts.size() > 8 &&
+ m_formspec_version <= FORMSPEC_API_VERSION)) {
+ errorstream << "Invalid model element (" << parts.size() << "): '" << element
+ << "'" << std::endl;
+ return;
+ }
+
+ // Avoid length checks by resizing
+ if (parts.size() < 8)
+ parts.resize(8);
+
+ 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]);
+ std::string meshstr = unescape_string(parts[3]);
+ std::vector<std::string> textures = split(parts[4], ',');
+ std::vector<std::string> vec_rot = split(parts[5], ',');
+ bool inf_rotation = is_yes(parts[6]);
+ bool mousectrl = is_yes(parts[7]) || parts[7].empty(); // default true
+
+ MY_CHECKPOS("model", 0);
+ MY_CHECKGEOM("model", 1);
+
+ v2s32 pos;
+ v2s32 geom;
+
+ if (data->real_coordinates) {
+ pos = getRealCoordinateBasePos(v_pos);
+ 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 (!data->explicit_size)
+ warningstream << "invalid use of model without a size[] element" << std::endl;
+
+ scene::IAnimatedMesh *mesh = m_client->getMesh(meshstr);
+
+ if (!mesh) {
+ errorstream << "Invalid model element: Unable to load mesh:"
+ << std::endl << "\t" << meshstr << std::endl;
+ return;
+ }
+
+ FieldSpec spec(
+ name,
+ L"",
+ L"",
+ 258 + m_fields.size()
+ );
+
+ core::rect<s32> rect(pos, pos + geom);
+
+ GUIScene *e = new GUIScene(Environment, RenderingEngine::get_scene_manager(),
+ data->current_parent, rect, spec.fid);
+
+ auto meshnode = e->setMesh(mesh);
+
+ for (u32 i = 0; i < textures.size() && i < meshnode->getMaterialCount(); ++i)
+ e->setTexture(i, m_tsrc->getTexture(textures[i]));
+
+ if (vec_rot.size() >= 2)
+ e->setRotation(v2f(stof(vec_rot[0]), stof(vec_rot[1])));
+
+ e->enableContinuousRotation(inf_rotation);
+ e->enableMouseControl(mousectrl);
+
+ auto style = getStyleForElement("model", spec.fname);
+ e->setStyles(style);
+ e->drop();
+
+ m_fields.push_back(spec);
+}
+
void GUIFormSpecMenu::parseElement(parserData* data, const std::string &element)
{
//some prechecks
@@ -2891,6 +2972,11 @@ void GUIFormSpecMenu::parseElement(parserData* data, const std::string &element)
return;
}
+ if (type == "model") {
+ parseModel(data, description);
+ return;
+ }
+
// Ignore others
infostream << "Unknown DrawSpec: type=" << type << ", data=\"" << description << "\""
<< std::endl;