+ e->setMultiLine(true);
+ e->setTextAlignment(gui::EGUIA_UPPERLEFT, gui::EGUIA_UPPERLEFT);
+ } else {
+ irr::SEvent evt;
+ evt.EventType = EET_KEY_INPUT_EVENT;
+ evt.KeyInput.Key = KEY_END;
+ evt.KeyInput.Char = 0;
+ evt.KeyInput.Control = 0;
+ evt.KeyInput.Shift = 0;
+ evt.KeyInput.PressedDown = true;
+ e->OnEvent(evt);
+ }
+
+ if (label.length() > 1)
+ {
+ rect.UpperLeftCorner.Y -= 15;
+ rect.LowerRightCorner.Y = rect.UpperLeftCorner.Y + 15;
+ Environment->addStaticText(spec.flabel.c_str(), rect, false, true, this, 0);
+ }
+ }
+ m_fields.push_back(spec);
+}
+
+void GUIFormSpecMenu::parseField(parserData* data,std::string element,std::string type) {
+ std::vector<std::string> parts = split(element,';',true);
+
+ if (parts.size() == 3) {
+ parseSimpleField(data,parts);
+ return;
+ }
+
+ if (parts.size() == 5) {
+ parseTextArea(data,parts,type);
+ return;
+ }
+ errorstream<< "Invalid field element(" << parts.size() << "): '" << element << "'" << std::endl;
+}
+
+void GUIFormSpecMenu::parseLabel(parserData* data,std::string element) {
+ std::vector<std::string> parts = split(element,';');
+
+ if (parts.size() == 2) {
+ std::vector<std::string> v_pos = split(parts[0],',');
+ std::string text = parts[1];
+
+ MY_CHECKPOS("label",0);
+
+ v2s32 pos = padding;
+ pos.X += stof(v_pos[0]) * (float)spacing.X;
+ pos.Y += stof(v_pos[1]) * (float)spacing.Y;
+
+ core::rect<s32> rect = core::rect<s32>(pos.X, pos.Y+((imgsize.Y/2)-15), pos.X+300, pos.Y+((imgsize.Y/2)+15));
+
+ if(data->bp_set != 2)
+ errorstream<<"WARNING: invalid use of label without a size[] element"<<std::endl;
+
+ text = unescape_string(text);
+
+ std::wstring wlabel = narrow_to_wide(text.c_str());
+
+ if (m_use_gettext)
+ wlabel = wstrgettext(text);
+
+ FieldSpec spec = FieldSpec(
+ L"",
+ wlabel,
+ L"",
+ 258+m_fields.size()
+ );
+ Environment->addStaticText(spec.flabel.c_str(), rect, false, true, this, spec.fid);
+ m_fields.push_back(spec);
+ return;
+ }
+ errorstream<< "Invalid label element(" << parts.size() << "): '" << element << "'" << std::endl;
+}
+
+void GUIFormSpecMenu::parseVertLabel(parserData* data,std::string element) {
+ std::vector<std::string> parts = split(element,';');
+
+ if (parts.size() == 2) {
+ std::vector<std::string> v_pos = split(parts[0],',');
+ std::string text = parts[1];
+
+ MY_CHECKPOS("vertlabel",1);
+
+ v2s32 pos = padding;
+ pos.X += stof(v_pos[0]) * (float)spacing.X;
+ pos.Y += stof(v_pos[1]) * (float)spacing.Y;
+
+ core::rect<s32> rect = core::rect<s32>(pos.X, pos.Y+((imgsize.Y/2)-15), pos.X+15, pos.Y+300);
+
+ if(data->bp_set != 2)
+ errorstream<<"WARNING: invalid use of label without a size[] element"<<std::endl;
+
+ text = unescape_string(text);
+ std::string label = "";
+
+ if (m_use_gettext) {
+ const char* toset = gettext(text.c_str());
+
+ text = std::string(toset);
+ }
+
+ for (unsigned int i=0; i < text.length(); i++) {
+ label += text.c_str()[i];
+ label += "\n";
+ }
+
+ FieldSpec spec = FieldSpec(
+ L"",
+ narrow_to_wide(label.c_str()),
+ L"",
+ 258+m_fields.size()
+ );
+ gui::IGUIStaticText *t =
+ Environment->addStaticText(spec.flabel.c_str(), rect, false, true, this, spec.fid);
+ t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_CENTER);
+ m_fields.push_back(spec);
+ return;
+ }
+ errorstream<< "Invalid vertlabel element(" << parts.size() << "): '" << element << "'" << std::endl;
+}
+
+void GUIFormSpecMenu::parseImageButton(parserData* data,std::string element,std::string type) {
+ std::vector<std::string> parts = split(element,';');
+
+ if ((parts.size() == 5) || (parts.size() == 7) || (parts.size() == 8)) {
+ std::vector<std::string> v_pos = split(parts[0],',');
+ std::vector<std::string> v_geom = split(parts[1],',');
+ std::string image_name = parts[2];
+ std::string name = parts[3];
+ std::string label = parts[4];
+
+ MY_CHECKPOS("imagebutton",0);
+ MY_CHECKGEOM("imagebutton",1);
+
+ v2s32 pos = padding;
+ pos.X += stof(v_pos[0]) * (float)spacing.X;
+ pos.Y += stof(v_pos[1]) * (float)spacing.Y;
+ 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);
+
+ bool noclip = false;
+ bool drawborder = true;
+
+ if ((parts.size() >= 7)) {
+ if (parts[5] == "true")
+ noclip = true;
+
+ if (parts[6] == "false")
+ drawborder = false;
+ }
+
+ std::string pressed_image_name = "";
+
+ if ((parts.size() == 8)) {
+ pressed_image_name = parts[7];
+ }
+
+ core::rect<s32> rect = core::rect<s32>(pos.X, pos.Y, pos.X+geom.X, pos.Y+geom.Y);
+
+ if(data->bp_set != 2)
+ errorstream<<"WARNING: invalid use of item_image_button without a size[] element"<<std::endl;
+
+ label = unescape_string(label);
+
+ std::wstring wlabel = narrow_to_wide(label.c_str());
+
+ if (m_use_gettext)
+ wlabel = wstrgettext(label);
+
+ FieldSpec spec = FieldSpec(
+ narrow_to_wide(name.c_str()),
+ wlabel,
+ narrow_to_wide(image_name.c_str()),
+ 258+m_fields.size()
+ );
+ spec.ftype = f_Button;
+ if(type == "image_button_exit")
+ spec.is_exit = true;
+
+ video::ITexture *texture = 0;
+ video::ITexture *pressed_texture = 0;
+ //if there's no gamedef specified try to get direct
+ //TODO check for possible texture leak
+ if (m_gamedef != 0) {
+ texture = m_gamedef->tsrc()->getTexture(image_name);
+ if ((parts.size() == 8)) {
+ pressed_texture = m_gamedef->tsrc()->getTexture(pressed_image_name);
+ }
+ } else {
+ if (fs::PathExists(image_name)) {
+ texture = Environment->getVideoDriver()->getTexture(image_name.c_str());
+ m_Textures.push_back(texture);
+ }
+ if (fs::PathExists(pressed_image_name)) {
+ pressed_texture = Environment->getVideoDriver()->getTexture(pressed_image_name.c_str());
+ m_Textures.push_back(pressed_texture);
+ }
+ }
+ if (parts.size() < 8)
+ pressed_texture = texture;
+
+ gui::IGUIButton *e = Environment->addButton(rect, this, spec.fid, spec.flabel.c_str());
+ e->setUseAlphaChannel(true);
+ e->setImage(texture);
+ e->setPressedImage(pressed_texture);
+ e->setScaleImage(true);
+ e->setNotClipped(noclip);
+ e->setDrawBorder(drawborder);
+
+ m_fields.push_back(spec);
+ return;
+ }
+
+ errorstream<< "Invalid imagebutton element(" << parts.size() << "): '" << element << "'" << std::endl;
+}
+
+void GUIFormSpecMenu::parseTabHeader(parserData* data,std::string element) {
+ std::vector<std::string> parts = split(element,';');
+
+ if ((parts.size() == 4) || (parts.size() == 6)) {
+ std::vector<std::string> v_pos = split(parts[0],',');
+ std::string name = parts[1];
+ std::vector<std::string> buttons = split(parts[2],',');
+ std::string str_index = parts[3];
+ bool show_background = true;
+ bool show_border = true;
+ int tab_index = stoi(str_index) -1;
+
+ MY_CHECKPOS("tabheader",0);
+
+ if (parts.size() == 6) {
+ if (parts[4] == "true")
+ show_background = false;
+ if (parts[5] == "false")
+ show_border = false;
+ }
+
+ FieldSpec spec = FieldSpec(
+ narrow_to_wide(name.c_str()),
+ L"",
+ L"",
+ 258+m_fields.size()
+ );
+
+ spec.ftype = f_TabHeader;
+
+ v2s32 pos = padding;
+ pos.X += stof(v_pos[0]) * (float)spacing.X;
+ pos.Y += stof(v_pos[1]) * (float)spacing.Y;
+ v2s32 geom;
+ geom.X = data->screensize.Y;
+ geom.Y = 30;
+
+ core::rect<s32> rect = core::rect<s32>(pos.X, pos.Y, pos.X+geom.X, pos.Y+geom.Y);
+
+ gui::IGUITabControl *e = Environment->addTabControl(rect,this,show_background,show_border,spec.fid);
+
+ e->setNotClipped(true);
+
+ for (unsigned int i=0; i< buttons.size(); i++) {
+ wchar_t* wbutton = 0;
+
+ if (m_use_gettext)
+ wbutton = wgettext(buttons[i].c_str());
+ else
+ wbutton = (wchar_t*) narrow_to_wide(buttons[i].c_str()).c_str();
+
+ e->addTab(wbutton,-1);
+
+ if (m_use_gettext)
+ delete[] wbutton;
+ }
+
+ if ((tab_index >= 0) &&
+ (buttons.size() < INT_MAX) &&
+ (tab_index < (int) buttons.size()))
+ e->setActiveTab(tab_index);
+
+ m_fields.push_back(spec);
+ return;
+ }
+ errorstream<< "Invalid TabHeader element(" << parts.size() << "): '" << element << "'" << std::endl;
+}
+
+void GUIFormSpecMenu::parseItemImageButton(parserData* data,std::string element) {
+
+ if (m_gamedef == 0) {
+ errorstream<<"WARNING: invalid use of item_image_button with m_gamedef==0"<<std::endl;
+ return;
+ }
+
+ std::vector<std::string> parts = split(element,';');
+
+ if (parts.size() == 5) {
+ std::vector<std::string> v_pos = split(parts[0],',');
+ std::vector<std::string> v_geom = split(parts[1],',');
+ std::string item_name = parts[2];
+ std::string name = parts[3];
+ std::string label = parts[4];
+
+ MY_CHECKPOS("itemimagebutton",0);
+ MY_CHECKGEOM("itemimagebutton",1);
+
+ v2s32 pos = padding;
+ pos.X += stof(v_pos[0]) * (float)spacing.X;
+ pos.Y += stof(v_pos[1]) * (float)spacing.Y;
+ 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);
+
+ core::rect<s32> rect = core::rect<s32>(pos.X, pos.Y, pos.X+geom.X, pos.Y+geom.Y);
+
+ if(data->bp_set != 2)
+ errorstream<<"WARNING: invalid use of item_image_button without a size[] element"<<std::endl;
+
+ IItemDefManager *idef = m_gamedef->idef();
+ ItemStack item;
+ item.deSerialize(item_name, idef);
+ video::ITexture *texture = idef->getInventoryTexture(item.getDefinition(idef).name, m_gamedef);
+ std::string tooltip = item.getDefinition(idef).description;
+
+ label = unescape_string(label);
+ FieldSpec spec = FieldSpec(
+ narrow_to_wide(name.c_str()),
+ narrow_to_wide(label.c_str()),
+ narrow_to_wide(item_name.c_str()),
+ 258+m_fields.size()
+ );
+
+ gui::IGUIButton *e = Environment->addButton(rect, this, spec.fid, spec.flabel.c_str());
+ e->setUseAlphaChannel(true);
+ e->setImage(texture);
+ e->setPressedImage(texture);
+ e->setScaleImage(true);
+ spec.ftype = f_Button;
+ rect+=data->basepos-padding;
+ spec.rect=rect;
+ if (tooltip!="")
+ spec.tooltip=tooltip;
+ m_fields.push_back(spec);
+ return;
+ }
+ errorstream<< "Invalid ItemImagebutton element(" << parts.size() << "): '" << element << "'" << std::endl;
+}
+
+void GUIFormSpecMenu::parseBox(parserData* data,std::string element) {
+ std::vector<std::string> parts = split(element,';');
+
+ if (parts.size() == 3) {
+ std::vector<std::string> v_pos = split(parts[0],',');
+ std::vector<std::string> v_geom = split(parts[1],',');
+ std::string color_str = parts[2];
+
+ MY_CHECKPOS("box",0);
+ MY_CHECKGEOM("box",1);
+
+ v2s32 pos = padding + AbsoluteRect.UpperLeftCorner;
+ pos.X += stof(v_pos[0]) * (float) spacing.X;
+ pos.Y += stof(v_pos[1]) * (float) spacing.Y;
+
+ v2s32 geom;
+ geom.X = stof(v_geom[0]) * (float)spacing.X;
+ geom.Y = stof(v_geom[1]) * (float)spacing.Y;
+
+ irr::video::SColor color;
+
+ if (parseColor(color_str, color)) {
+ BoxDrawSpec spec(pos,geom,color);
+
+ m_boxes.push_back(spec);
+ }
+ else {
+ errorstream<< "Invalid Box element(" << parts.size() << "): '" << element << "' INVALID COLOR" << std::endl;
+ }
+ return;
+ }
+ errorstream<< "Invalid Box element(" << parts.size() << "): '" << element << "'" << std::endl;
+}
+
+void GUIFormSpecMenu::parseElement(parserData* data,std::string element) {
+
+ //some prechecks
+ if (element == "")
+ return;
+
+ std::vector<std::string> parts = split(element,'[', true);
+
+ // ugly workaround to keep compatibility
+ if (parts.size() > 2) {
+ if (trim(parts[0]) == "image") {
+ for (unsigned int i=2;i< parts.size(); i++) {
+ parts[1] += "[" + parts[i];
+ }
+ }
+ else { return; }
+ }
+
+ if (parts.size() < 2) {
+ return;
+ }
+
+ std::string type = trim(parts[0]);
+ std::string description = trim(parts[1]);
+
+ if ((type == "size") || (type == "invsize")){
+ parseSize(data,description);
+ return;
+ }
+
+ if (type == "list") {
+ parseList(data,description);
+ return;
+ }
+
+ if (type == "checkbox") {
+ parseCheckbox(data,description);
+ return;
+ }
+
+ if (type == "image") {
+ parseImage(data,description);
+ return;
+ }
+
+ if (type == "item_image") {
+ parseItemImage(data,description);
+ return;
+ }
+
+ if ((type == "button") || (type == "button_exit")) {
+ parseButton(data,description,type);
+ return;
+ }
+
+ if (type == "background") {
+ parseBackground(data,description);
+ return;
+ }
+
+ if (type == "textlist"){
+ parseTextList(data,description);
+ return;
+ }
+
+ if (type == "dropdown"){
+ parseDropDown(data,description);
+ return;
+ }
+
+ if (type == "pwdfield") {
+ parsePwdField(data,description);
+ return;
+ }
+
+ if ((type == "field") || (type == "textarea")){
+ parseField(data,description,type);
+ return;
+ }
+
+ if (type == "label") {
+ parseLabel(data,description);
+ return;
+ }
+
+ if (type == "vertlabel") {
+ parseVertLabel(data,description);
+ return;
+ }
+
+ if (type == "item_image_button") {
+ parseItemImageButton(data,description);
+ return;
+ }
+
+ if ((type == "image_button") || (type == "image_button_exit")) {
+ parseImageButton(data,description,type);
+ return;
+ }
+
+ if (type == "tabheader") {
+ parseTabHeader(data,description);
+ return;
+ }
+
+ if (type == "box") {
+ parseBox(data,description);
+ return;
+ }
+
+ // Ignore others
+ infostream
+ << "Unknown DrawSpec: type="<<type<<", data=\""<<description<<"\""
+ <<std::endl;
+}
+
+
+
+void GUIFormSpecMenu::regenerateGui(v2u32 screensize)
+{
+ parserData mydata;
+
+ //preserve listboxes
+ for (unsigned int i = 0; i < m_listboxes.size(); i++) {
+ int selection = m_listboxes[i].second->getSelected();
+ if (selection != -1) {
+ std::wstring listboxname = m_listboxes[i].first.fname;
+ mydata.listbox_selections[listboxname] = selection;
+ }
+ }
+
+ // Remove children
+ removeChildren();
+
+ mydata.size= v2s32(100,100);
+ mydata.helptext_h = 15;
+ mydata.screensize = screensize;
+
+ // Base position of contents of form
+ mydata.basepos = getBasePos();