From 967121a34bbc60e6b46c7ec470b151f668ef1fef Mon Sep 17 00:00:00 2001 From: sapier Date: Sun, 23 Jun 2013 18:30:21 +0200 Subject: Replace C++ mainmenu by formspec powered one --- src/guiFormSpecMenu.cpp | 2072 ++++++++++++++++++++++++++++++++++++----------- 1 file changed, 1618 insertions(+), 454 deletions(-) (limited to 'src/guiFormSpecMenu.cpp') diff --git a/src/guiFormSpecMenu.cpp b/src/guiFormSpecMenu.cpp index ee39df8b7..0aa2c2dcd 100644 --- a/src/guiFormSpecMenu.cpp +++ b/src/guiFormSpecMenu.cpp @@ -18,6 +18,11 @@ with this program; if not, write to the Free Software Foundation, Inc., */ +#include +#include +#include +#include +#include #include "guiFormSpecMenu.h" #include "constants.h" #include "gamedef.h" @@ -28,13 +33,34 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include +#include +#include +#include +#include #include "log.h" #include "tile.h" // ITextureSource #include "util/string.h" #include "util/numeric.h" +#include "filesys.h" #include "gettext.h" + +#define MY_CHECKPOS(a,b) \ + if (v_pos.size() != 2) { \ + errorstream<< "Invalid pos for element " << a << "specified: \"" \ + << parts[b] << "\"" << std::endl; \ + return; \ + } + +#define MY_CHECKGEOM(a,b) \ + if (v_geom.size() != 2) { \ + errorstream<< "Invalid pos for element " << a << "specified: \"" \ + << parts[b] << "\"" << std::endl; \ + return; \ + } + + void drawItemStack(video::IVideoDriver *driver, gui::IGUIFont *font, const ItemStack &item, @@ -140,7 +166,10 @@ GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev, m_selected_item(NULL), m_selected_amount(0), m_selected_dragging(false), - m_tooltip_element(NULL) + m_tooltip_element(NULL), + m_allowclose(true), + m_use_gettext(false), + m_lock(false) { } @@ -148,53 +177,1315 @@ GUIFormSpecMenu::~GUIFormSpecMenu() { removeChildren(); - delete m_selected_item; - delete m_form_src; - delete m_text_dst; -} + delete m_selected_item; + delete m_form_src; + delete m_text_dst; +} + +void GUIFormSpecMenu::removeChildren() +{ + const core::list &children = getChildren(); + core::list children_copy; + for(core::list::ConstIterator + i = children.begin(); i != children.end(); i++) + { + children_copy.push_back(*i); + } + for(core::list::Iterator + i = children_copy.begin(); + i != children_copy.end(); i++) + { + (*i)->remove(); + } + /*{ + gui::IGUIElement *e = getElementFromId(256); + if(e != NULL) + e->remove(); + }*/ + if(m_tooltip_element) + { + m_tooltip_element->remove(); + m_tooltip_element = NULL; + } +} + +int GUIFormSpecMenu::getListboxIndex(std::string listboxname) { + + std::wstring wlistboxname = narrow_to_wide(listboxname.c_str()); + + for(unsigned int i=0; i < m_listboxes.size(); i++) { + + std::wstring name(m_listboxes[i].first.fname.c_str()); + if ( name == wlistboxname) { + return m_listboxes[i].second->getSelected(); + } + } + return -1; +} + +std::vector split(const std::string &s, char delim, bool escape=false) { + std::vector tokens; + + if (!escape) { + int startpos = 0; + size_t nextpos = s.find(delim); + + while(nextpos != std::string::npos) { + std::string toadd = s.substr(startpos,nextpos-startpos); + tokens.push_back(toadd); + startpos = nextpos+1; + nextpos = s.find(delim,nextpos+1); + } + + //push last element + tokens.push_back(s.substr(startpos)); + } + else { + std::string current = ""; + current += s.c_str()[0]; + bool last_was_delim = false; + for(unsigned int i=1; i < s.size(); i++) { + if (last_was_delim) { + if (s.c_str()[i] == delim) { + current += s.c_str()[i]; + last_was_delim = false; + } + else { + tokens.push_back(current); + + current = ""; + current += s.c_str()[i]; + last_was_delim = false; + } + } + else { + if (s.c_str()[i] == delim) { + last_was_delim = true; + } + else { + last_was_delim = false; + current += s.c_str()[i]; + } + } + } + //push last element + tokens.push_back(current); + } + + return tokens; +} + +void GUIFormSpecMenu::parseSize(parserData* data,std::string element) { + std::vector parts = split(element,','); + + if (parts.size() == 2) { + v2f invsize; + + if (parts[1].find(';') != std::string::npos) + parts[1] = parts[1].substr(0,parts[1].find(';')); + + invsize.X = stof(parts[0]); + invsize.Y = stof(parts[1]); + + infostream<<"Form size ("<getVideoDriver()->getScreenSize(); + v2u32 delta = current_screensize - m_lockscreensize; + + if (current_screensize.Y > m_lockscreensize.Y) + delta.Y /= 2; + else + delta.Y = 0; + + if (current_screensize.X > m_lockscreensize.X) + delta.X /= 2; + else + delta.X = 0; + + offset = v2s32(delta.X,delta.Y); + + data->screensize = m_lockscreensize; + } + else { + offset = v2s32(0,0); + } + + padding = v2s32(data->screensize.Y/40, data->screensize.Y/40); + spacing = v2s32(data->screensize.Y/12, data->screensize.Y/13); + imgsize = v2s32(data->screensize.Y/15, data->screensize.Y/15); + data->size = v2s32( + padding.X*2+spacing.X*(invsize.X-1.0)+imgsize.X, + padding.Y*2+spacing.Y*(invsize.Y-1.0)+imgsize.Y + (data->helptext_h-5) + ); + data->rect = core::rect( + data->screensize.X/2 - data->size.X/2 + offset.X, + data->screensize.Y/2 - data->size.Y/2 + offset.Y, + data->screensize.X/2 + data->size.X/2 + offset.X, + data->screensize.Y/2 + data->size.Y/2 + offset.Y + ); + + DesiredRect = data->rect; + recalculateAbsolutePosition(false); + data->basepos = getBasePos(); + data->bp_set = 2; + return; + } + errorstream<< "Invalid size element (" << parts.size() << "): '" << element << "'" << std::endl; +} + +void GUIFormSpecMenu::parseList(parserData* data,std::string element) { + + if (m_gamedef == 0) { + errorstream<<"WARNING: invalid use of 'list' with m_gamedef==0"< parts = split(element,';'); + + if ((parts.size() == 4) || (parts.size() == 5)) { + std::string location = parts[0]; + std::string listname = parts[1]; + std::vector v_pos = split(parts[2],','); + std::vector v_geom = split(parts[3],','); + std::string startindex = ""; + if (parts.size() == 5) + startindex = parts[4]; + + MY_CHECKPOS("list",2); + MY_CHECKGEOM("list",3); + + InventoryLocation loc; + + if(location == "context" || location == "current_name") + loc = m_current_inventory_location; + else + loc.deSerialize(location); + + 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 = stoi(v_geom[0]); + geom.Y = stoi(v_geom[1]); + infostream<<"list inv="<bp_set != 2) + errorstream<<"WARNING: invalid use of list without a size[] element"< parts = split(element,';'); + + if ((parts.size() == 3) || (parts.size() == 4)) { + std::vector v_pos = split(parts[0],','); + std::string name = parts[1]; + std::string label = parts[2]; + std::string selected = ""; + + if (parts.size() == 4) + selected = parts[3]; + + MY_CHECKPOS("checkbox",0); + + v2s32 pos = padding; + pos.X += stof(v_pos[0]) * (float) spacing.X; + pos.Y += stof(v_pos[1]) * (float) spacing.Y; + + core::rect rect = core::rect(pos.X, pos.Y+((imgsize.Y/2)-15), pos.X+300, pos.Y+((imgsize.Y/2)+15)); + + bool fselected = false; + + if (selected == "true") + fselected = true; + + wchar_t* wlabel = 0; + + if (m_use_gettext) + wlabel = wgettext(label.c_str()); + else + wlabel = (wchar_t*) narrow_to_wide(label.c_str()).c_str(); + + FieldSpec spec = FieldSpec( + narrow_to_wide(name.c_str()), + narrow_to_wide(""), + wlabel, + 258+m_fields.size() + ); + + spec.ftype = f_CheckBox; + + gui::IGUICheckBox* e = Environment->addCheckBox(fselected, rect, this, + spec.fid, wlabel); + + m_checkboxes.push_back(std::pair(spec,e)); + m_fields.push_back(spec); + if (m_use_gettext) + delete[] wlabel; + return; + } + errorstream<< "Invalid checkbox element(" << parts.size() << "): '" << element << "'" << std::endl; +} + +void GUIFormSpecMenu::parseImage(parserData* data,std::string element) { + std::vector parts = split(element,';'); + + if (parts.size() == 3) { + std::vector v_pos = split(parts[0],','); + std::vector v_geom = split(parts[1],','); + std::string name = parts[2]; + + MY_CHECKPOS("image",0); + MY_CHECKGEOM("image",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 = stoi(v_geom[0]) * (float)imgsize.X; + geom.Y = stoi(v_geom[1]) * (float)imgsize.Y; + + infostream<<"image name="<bp_set != 2) + errorstream<<"WARNING: invalid use of image without a size[] element"< v_pos = split(parts[0],','); + std::string name = parts[1]; + + MY_CHECKPOS("image",0); + + v2s32 pos = padding + AbsoluteRect.UpperLeftCorner; + pos.X += stof(v_pos[0]) * (float) spacing.X; + pos.Y += stof(v_pos[1]) * (float) spacing.Y; + + std::cout<<"image name="<bp_set != 2) + errorstream<<"WARNING: invalid use of image without a size[] element"< parts = split(element,';'); + + if (parts.size() == 3) { + std::vector v_pos = split(parts[0],','); + std::vector v_geom = split(parts[1],','); + std::string name = parts[2]; + + MY_CHECKPOS("itemimage",0); + MY_CHECKGEOM("itemimage",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 = stoi(v_geom[0]) * (float)imgsize.X; + geom.Y = stoi(v_geom[1]) * (float)imgsize.Y; + + infostream<<"item name="<bp_set != 2) + errorstream<<"WARNING: invalid use of item_image without a size[] element"< parts = split(element,';'); + + if (parts.size() == 4) { + std::vector v_pos = split(parts[0],','); + std::vector v_geom = split(parts[1],','); + std::string name = parts[2]; + std::string label = parts[3]; + + MY_CHECKPOS("button",0); + MY_CHECKGEOM("button",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); + pos.Y += (stof(v_geom[1]) * (float)imgsize.Y)/2; + + core::rect rect = core::rect(pos.X, pos.Y-15, pos.X+geom.X, pos.Y+15); + + if(data->bp_set != 2) + errorstream<<"WARNING: invalid use of button without a size[] element"<addButton(rect, this, spec.fid, spec.flabel.c_str()); + m_fields.push_back(spec); + if (m_use_gettext) + delete[] wlabel; + return; + } + errorstream<< "Invalid button element(" << parts.size() << "): '" << element << "'" << std::endl; +} + +void GUIFormSpecMenu::parseBackground(parserData* data,std::string element) { + std::vector parts = split(element,';'); + + if (parts.size() == 3) { + std::vector v_pos = split(parts[0],','); + std::vector v_geom = split(parts[1],','); + std::string name = parts[2]; + + MY_CHECKPOS("background",0); + MY_CHECKGEOM("background",1); + + v2s32 pos = padding + AbsoluteRect.UpperLeftCorner; + 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 geom; + geom.X = stof(v_geom[0]) * (float)spacing.X; + geom.Y = stof(v_geom[1]) * (float)spacing.Y; + + infostream<<"image name="<bp_set != 2) + errorstream<<"WARNING: invalid use of background without a size[] element"< parts = split(element,';'); + + if ((parts.size() == 5) || (parts.size() == 6)) { + std::vector v_pos = split(parts[0],','); + std::vector v_geom = split(parts[1],','); + std::string name = parts[2]; + std::vector items = split(parts[3],','); + std::string str_initial_selection = ""; + std::string str_transparent = "false"; + + if (parts.size() >= 5) + str_initial_selection = parts[4]; + + if (parts.size() >= 6) + str_transparent = parts[5]; + + MY_CHECKPOS("textlist",0); + MY_CHECKGEOM("textlist",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; + geom.Y = stof(v_geom[1]) * (float)spacing.Y; + + + core::rect rect = core::rect(pos.X, pos.Y, pos.X+geom.X, pos.Y+geom.Y); + + std::wstring fname_w = narrow_to_wide(name.c_str()); + + FieldSpec spec = FieldSpec( + fname_w, + narrow_to_wide(""), + narrow_to_wide(""), + 258+m_fields.size() + ); + + spec.ftype = f_ListBox; + + //now really show list + gui::IGUIListBox *e = Environment->addListBox(rect, this,spec.fid); + + //don't reset if we already have a user specified selection + if (data->listbox_selections.find(fname_w) == data->listbox_selections.end()) { + e->setAutoScrollEnabled(false); + } + + if (str_transparent == "false") + e->setDrawBackground(true); + + for (unsigned int i=0; i < items.size(); i++) { + if (items[i].c_str()[0] == '#') { + if (items[i].c_str()[1] == '#') { + e->addItem(narrow_to_wide(items[i]).c_str() +1); + } + else { + std::wstring toadd = narrow_to_wide(items[i].c_str() + 4); + std::string color = items[i].substr(1,3); + + e->addItem(toadd.c_str()); + + bool valid_color = true; + + irr::video::SColor toset = getColor(color,valid_color); + + if (valid_color) + e->setItemOverrideColor(i,toset); + } + } + else { + e->addItem(narrow_to_wide(items[i]).c_str()); + } + } + + if (str_initial_selection != "") + e->setSelected(stoi(str_initial_selection.c_str())-1); + + if (data->listbox_selections.find(fname_w) != data->listbox_selections.end()) { + e->setSelected(data->listbox_selections[fname_w]); + } + + m_listboxes.push_back(std::pair(spec,e)); + m_fields.push_back(spec); + return; + } + errorstream<< "Invalid textlist element(" << parts.size() << "): '" << element << "'" << std::endl; +} + + +void GUIFormSpecMenu::parseDropDown(parserData* data,std::string element) { + std::vector parts = split(element,';'); + + if (parts.size() == 5) { + std::vector v_pos = split(parts[0],','); + std::string name = parts[2]; + std::vector items = split(parts[3],','); + std::string str_initial_selection = ""; + str_initial_selection = parts[4]; + + MY_CHECKPOS("dropdown",0); + + v2s32 pos = padding; + pos.X += stof(v_pos[0]) * (float)spacing.X; + pos.Y += stof(v_pos[1]) * (float)spacing.Y; + + s32 width = stof(parts[1]) * (float)spacing.Y; + + core::rect rect = core::rect(pos.X, pos.Y, pos.X+width, pos.Y+30); + + std::wstring fname_w = narrow_to_wide(name.c_str()); + + FieldSpec spec = FieldSpec( + fname_w, + narrow_to_wide(""), + narrow_to_wide(""), + 258+m_fields.size() + ); + + spec.ftype = f_DropDown; + spec.send = true; + + //now really show list + gui::IGUIComboBox *e = Environment->addComboBox(rect, this,spec.fid); + + //don't reset if we already have a user specified selection + //if (data->combobox_selections.find(fname_w) == data->listbox_selections.end()) { + // e->setAutoScrollEnabled(false); + //} + + for (unsigned int i=0; i < items.size(); i++) { + e->addItem(narrow_to_wide(items[i]).c_str()); + } + + if (str_initial_selection != "") + e->setSelected(stoi(str_initial_selection.c_str())-1); + + //if (data->listbox_selections.find(fname_w) != data->listbox_selections.end()) { + // e->setSelected(data->listbox_selections[fname_w]); + //} + + //m_listboxes.push_back(std::pair(spec,e)); + m_fields.push_back(spec); + return; + } + errorstream << "Invalid dropdown element(" << parts.size() << "): '" + << element << "'" << std::endl; +} + +void GUIFormSpecMenu::parsePwdField(parserData* data,std::string element) { + std::vector parts = split(element,';'); + + if (parts.size() == 4) { + std::vector v_pos = split(parts[0],','); + std::vector v_geom = split(parts[1],','); + std::string name = parts[2]; + std::string label = parts[3]; + + MY_CHECKPOS("pwdfield",0); + MY_CHECKGEOM("pwdfield",1); + + v2s32 pos; + 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); + + pos.Y += (stof(v_geom[1]) * (float)imgsize.Y)/2; + pos.Y -= 15; + geom.Y = 30; + + core::rect rect = core::rect(pos.X, pos.Y, pos.X+geom.X, pos.Y+geom.Y); + + label = unescape_string(label); + + wchar_t* wlabel = 0; + + if (m_use_gettext) { + if (label.length() > 1) + wlabel = wgettext(label.c_str()); + else + wlabel = (wchar_t*) narrow_to_wide("").c_str(); + } + else + wlabel = (wchar_t*) narrow_to_wide(label.c_str()).c_str(); + + FieldSpec spec = FieldSpec( + narrow_to_wide(name.c_str()), + wlabel, + narrow_to_wide(""), + 258+m_fields.size() + ); + + spec.send = true; + gui::IGUIEditBox * e = Environment->addEditBox(0, rect, true, this, spec.fid); + Environment->setFocus(e); + + 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); + } + + e->setPasswordBox(true,L'*'); + + irr::SEvent evt; + evt.KeyInput.Key = KEY_END; + evt.EventType = EET_KEY_INPUT_EVENT; + evt.KeyInput.PressedDown = true; + e->OnEvent(evt); + m_fields.push_back(spec); + if ((m_use_gettext) && (label.length() >1)) + delete[] wlabel; + return; + } + errorstream<< "Invalid pwdfield element(" << parts.size() << "): '" << element << "'" << std::endl; +} + +void GUIFormSpecMenu::parseSimpleField(parserData* data,std::vector &parts) { + std::string name = parts[0]; + std::string label = parts[1]; + std::string default_val = parts[2]; + + core::rect rect; + + if(!data->bp_set) + { + rect = core::rect( + data->screensize.X/2 - 580/2, + data->screensize.Y/2 - 300/2, + data->screensize.X/2 + 580/2, + data->screensize.Y/2 + 300/2 + ); + DesiredRect = rect; + recalculateAbsolutePosition(false); + data->basepos = getBasePos(); + data->bp_set = 1; + } + else if(data->bp_set == 2) + errorstream<<"WARNING: invalid use of unpositioned \"field\" in inventory"<(size.X/2-150, pos.Y, (size.X/2-150)+300, pos.Y+30); + + + if(m_form_src) + default_val = m_form_src->resolveText(default_val); + + default_val = unescape_string(default_val); + label = unescape_string(label); + + wchar_t* wlabel = 0; + + if (m_use_gettext) { + if (label.length() > 1) + wlabel = wgettext(label.c_str()); + else + wlabel = (wchar_t*) narrow_to_wide("").c_str(); + } + else + wlabel = (wchar_t*) narrow_to_wide(label.c_str()).c_str(); + + FieldSpec spec = FieldSpec( + narrow_to_wide(name.c_str()), + wlabel, + narrow_to_wide(default_val.c_str()), + 258+m_fields.size() + ); + + if (name == "") + { + // spec field id to 0, this stops submit searching for a value that isn't there + Environment->addStaticText(spec.flabel.c_str(), rect, false, true, this, spec.fid); + } + else + { + spec.send = true; + gui::IGUIEditBox *e = Environment->addEditBox(spec.fdefault.c_str(), rect, true, this, spec.fid); + Environment->setFocus(e); + + irr::SEvent evt; + evt.KeyInput.Key = KEY_END; + evt.EventType = EET_KEY_INPUT_EVENT; + 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); + } + } + if (m_use_gettext && (label.length() > 1)) + delete[] wlabel; + + m_fields.push_back(spec); +} + +void GUIFormSpecMenu::parseTextArea(parserData* data,std::vector& parts,std::string type) { + + std::vector v_pos = split(parts[0],','); + std::vector v_geom = split(parts[1],','); + std::string name = parts[2]; + std::string label = parts[3]; + std::string default_val = parts[4]; + + MY_CHECKPOS(type,0); + MY_CHECKGEOM(type,1); + + v2s32 pos; + 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); + + if (type == "textarea") + { + geom.Y = (stof(v_geom[1]) * (float)imgsize.Y) - (spacing.Y-imgsize.Y); + pos.Y += 15; + } + else + { + pos.Y += (stof(v_geom[1]) * (float)imgsize.Y)/2; + pos.Y -= 15; + geom.Y = 30; + } + + core::rect rect = core::rect(pos.X, pos.Y, pos.X+geom.X, pos.Y+geom.Y); + + if(data->bp_set != 2) + errorstream<<"WARNING: invalid use of positioned "<resolveText(default_val); + + + default_val = unescape_string(default_val); + label = unescape_string(label); + + wchar_t* wlabel = 0; + + if (m_use_gettext) { + if (label.length() > 1) + wlabel = wgettext(label.c_str()); + else + wlabel = (wchar_t*) narrow_to_wide("").c_str(); + } + else + wlabel = (wchar_t*) narrow_to_wide(label.c_str()).c_str(); + + FieldSpec spec = FieldSpec( + narrow_to_wide(name.c_str()), + wlabel, + narrow_to_wide(default_val.c_str()), + 258+m_fields.size() + ); + + if (name == "") + { + // spec field id to 0, this stops submit searching for a value that isn't there + Environment->addStaticText(spec.flabel.c_str(), rect, false, true, this, spec.fid); + } + else + { + spec.send = true; + gui::IGUIEditBox *e = Environment->addEditBox(spec.fdefault.c_str(), rect, true, this, spec.fid); + Environment->setFocus(e); + + if (type == "textarea") + { + 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); + } + } + if (m_use_gettext && (label.length() > 1)) + delete[] wlabel; + m_fields.push_back(spec); +} + +void GUIFormSpecMenu::parseField(parserData* data,std::string element,std::string type) { + std::vector parts = split(element,';'); + + 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 parts = split(element,';'); + + if (parts.size() == 2) { + std::vector 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 rect = core::rect(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"<addStaticText(spec.flabel.c_str(), rect, false, true, this, spec.fid); + m_fields.push_back(spec); + if (m_use_gettext) + delete[] wlabel; + return; + } + errorstream<< "Invalid label element(" << parts.size() << "): '" << element << "'" << std::endl; +} + +void GUIFormSpecMenu::parseVertLabel(parserData* data,std::string element) { + std::vector parts = split(element,';'); + + if (parts.size() == 2) { + std::vector 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 rect = core::rect(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"<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 parts = split(element,';'); + + if ((parts.size() == 5) || (parts.size() == 7)) { + std::vector v_pos = split(parts[0],','); + std::vector 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; + } + + core::rect rect = core::rect(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"<tsrc()->getTexture(image_name); + else { + if (fs::PathExists(image_name)) { + texture = Environment->getVideoDriver()->getTexture(image_name.c_str()); + m_Textures.push_back(texture); + } + } + + 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); + 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 parts = split(element,';'); + + if ((parts.size() == 4) || (parts.size() == 6)) { + std::vector v_pos = split(parts[0],','); + std::string name = parts[1]; + std::vector 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()), + narrow_to_wide(""), + narrow_to_wide(""), + 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 rect = core::rect(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"< parts = split(element,';'); + + if (parts.size() == 5) { + std::vector v_pos = split(parts[0],','); + std::vector 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 rect = core::rect(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"<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 parts = split(element,';'); + + if (parts.size() == 3) { + std::vector v_pos = split(parts[0],','); + std::vector 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; + + bool valid_color = false; + + irr::video::SColor color = getColor(color_str,valid_color); + + if (valid_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 parts = split(element,'[', true); + + 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; + } -void GUIFormSpecMenu::removeChildren() -{ - const core::list &children = getChildren(); - core::list children_copy; - for(core::list::ConstIterator - i = children.begin(); i != children.end(); i++) - { - children_copy.push_back(*i); + if (type == "item_image_button") { + parseItemImageButton(data,description); + return; } - for(core::list::Iterator - i = children_copy.begin(); - i != children_copy.end(); i++) - { - (*i)->remove(); + + if ((type == "image_button") || (type == "image_button_exit")) { + parseImageButton(data,description,type); + return; } - /*{ - gui::IGUIElement *e = getElementFromId(256); - if(e != NULL) - e->remove(); - }*/ - if(m_tooltip_element) - { - m_tooltip_element->remove(); - m_tooltip_element = NULL; + + if (type == "tabheader") { + parseTabHeader(data,description); + return; + } + + if (type == "box") { + parseBox(data,description); + return; } + + // Ignore others + infostream + << "Unknown DrawSpec: type="<getSelected(); + if (selection != -1) { + std::wstring listboxname = m_listboxes[i].first.fname; + mydata.listbox_selections[listboxname] = selection; + } + } + // Remove children removeChildren(); - - v2s32 size(100,100); - s32 helptext_h = 15; - core::rect rect; + + mydata.size= v2s32(100,100); + mydata.helptext_h = 15; + mydata.screensize = screensize; // Base position of contents of form - v2s32 basepos = getBasePos(); + mydata.basepos = getBasePos(); + // State of basepos, 0 = not set, 1= set by formspec, 2 = set by size[] element // Used to adjust form size automatically if needed // A proceed button is added if there is no size[] element - int bp_set = 0; + mydata.bp_set = 0; + /* Convert m_init_draw_spec to m_inventorylists */ @@ -202,414 +1493,53 @@ void GUIFormSpecMenu::regenerateGui(v2u32 screensize) m_images.clear(); m_backgrounds.clear(); m_itemimages.clear(); + m_listboxes.clear(); + m_checkboxes.clear(); m_fields.clear(); + m_boxes.clear(); - Strfnd f(m_formspec_string); - while(f.atend() == false) - { - std::string type = trim(f.next_esc("[")); - if(type == "invsize" || type == "size") - { - v2f invsize; - invsize.X = stof(f.next_esc(",")); - if(type == "size") - { - invsize.Y = stof(f.next_esc("]")); - } - else{ - invsize.Y = stof(f.next_esc(";")); - f.next_esc("]"); - } - infostream<<"Form size ("<( - screensize.X/2 - size.X/2, - screensize.Y/2 - size.Y/2, - screensize.X/2 + size.X/2, - screensize.Y/2 + size.Y/2 - ); - DesiredRect = rect; - recalculateAbsolutePosition(false); - basepos = getBasePos(); - bp_set = 2; - } - else if(type == "list") - { - std::string name = f.next_esc(";"); - InventoryLocation loc; - if(name == "context" || name == "current_name") - loc = m_current_inventory_location; - else - loc.deSerialize(name); - std::string listname = f.next_esc(";"); - v2s32 pos = basepos; - pos.X += stof(f.next_esc(",")) * (float)spacing.X; - pos.Y += stof(f.next_esc(";")) * (float)spacing.Y; - v2s32 geom; - geom.X = stoi(f.next_esc(",")); - geom.Y = stoi(f.next_esc(";")); - infostream<<"list inv="<( - screensize.X/2 - 580/2, - screensize.Y/2 - 300/2, - screensize.X/2 + 580/2, - screensize.Y/2 + 300/2 - ); - DesiredRect = rect; - recalculateAbsolutePosition(false); - basepos = getBasePos(); - bp_set = 1; - } - else if(bp_set == 2) - errorstream<<"WARNING: invalid use of unpositioned "<(size.X/2-150, pos.Y, (size.X/2-150)+300, pos.Y+30); - } - else - { - v2s32 pos; - pos.X = stof(fname.substr(0,fname.find(","))) * (float)spacing.X; - pos.Y = stof(fname.substr(fname.find(",")+1)) * (float)spacing.Y; - v2s32 geom; - geom.X = (stof(flabel.substr(0,flabel.find(","))) * (float)spacing.X)-(spacing.X-imgsize.X); - if (type == "textarea") - { - geom.Y = (stof(flabel.substr(flabel.find(",")+1)) * (float)imgsize.Y) - (spacing.Y-imgsize.Y); - pos.Y += 15; - } - else - { - pos.Y += (stof(flabel.substr(flabel.find(",")+1)) * (float)imgsize.Y)/2; - pos.Y -= 15; - geom.Y = 30; - } - - rect = core::rect(pos.X, pos.Y, pos.X+geom.X, pos.Y+geom.Y); - - - - fname = f.next_esc(";"); - flabel = f.next_esc(";"); - if(bp_set != 2) - errorstream<<"WARNING: invalid use of positioned "<resolveText(odefault); - else - fdefault = odefault; - - fdefault = unescape_string(fdefault); - flabel = unescape_string(flabel); - - FieldSpec spec = FieldSpec( - narrow_to_wide(fname.c_str()), - narrow_to_wide(flabel.c_str()), - narrow_to_wide(fdefault.c_str()), - 258+m_fields.size() - ); - - // three cases: field name and no label, label and field, label name and no field - gui::IGUIEditBox *e; - if (fname == "") - { - // spec field id to 0, this stops submit searching for a value that isn't there - Environment->addStaticText(spec.flabel.c_str(), rect, false, true, this, spec.fid); - } - else - { - spec.send = true; - e = Environment->addEditBox(spec.fdefault.c_str(), rect, true, this, spec.fid); - Environment->setFocus(e); - - if (type == "textarea") - { - 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.PressedDown = true; - evt.KeyInput.Char = 0; - evt.KeyInput.Control = 0; - evt.KeyInput.Shift = 0; - e->OnEvent(evt); - } - - if (flabel != "") - { - 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); - } - else if(type == "label") - { - v2s32 pos = padding; - pos.X += stof(f.next_esc(",")) * (float)spacing.X; - pos.Y += stof(f.next_esc(";")) * (float)spacing.Y; - rect = core::rect(pos.X, pos.Y+((imgsize.Y/2)-15), pos.X+300, pos.Y+((imgsize.Y/2)+15)); - - std::string flabel = f.next_esc("]"); - if(bp_set != 2) - errorstream<<"WARNING: invalid use of label without a size[] element"< elements = split(m_formspec_string,']',true); - flabel = unescape_string(flabel); - - FieldSpec spec = FieldSpec( - narrow_to_wide(""), - narrow_to_wide(flabel.c_str()), - narrow_to_wide(""), - 258+m_fields.size() - ); - Environment->addStaticText(spec.flabel.c_str(), rect, false, true, this, spec.fid); - m_fields.push_back(spec); - } - else if(type == "button" || type == "button_exit") - { - v2s32 pos = padding; - pos.X += stof(f.next_esc(",")) * (float)spacing.X; - pos.Y += stof(f.next_esc(";")) * (float)spacing.Y; - v2s32 geom; - geom.X = (stof(f.next_esc(",")) * (float)spacing.X)-(spacing.X-imgsize.X); - pos.Y += (stof(f.next_esc(";")) * (float)imgsize.Y)/2; - - rect = core::rect(pos.X, pos.Y-15, pos.X+geom.X, pos.Y+15); - - std::string fname = f.next_esc(";"); - std::string flabel = f.next_esc("]"); - if(bp_set != 2) - errorstream<<"WARNING: invalid use of button without a size[] element"<addButton(rect, this, spec.fid, spec.flabel.c_str()); - m_fields.push_back(spec); - } - else if(type == "image_button" || type == "image_button_exit") - { - v2s32 pos = padding; - pos.X += stof(f.next_esc(",")) * (float)spacing.X; - pos.Y += stof(f.next_esc(";")) * (float)spacing.Y; - v2s32 geom; - geom.X = (stof(f.next_esc(",")) * (float)spacing.X)-(spacing.X-imgsize.X); - geom.Y = (stof(f.next_esc(";")) * (float)spacing.Y)-(spacing.Y-imgsize.Y); - - rect = core::rect(pos.X, pos.Y, pos.X+geom.X, pos.Y+geom.Y); - - std::string fimage = f.next_esc(";"); - std::string fname = f.next_esc(";"); - std::string flabel = f.next_esc("]"); - if(bp_set != 2) - errorstream<<"WARNING: invalid use of image_button without a size[] element"<tsrc()->getTexture(fimage); - 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); - - m_fields.push_back(spec); - } - else if(type == "item_image_button") - { - v2s32 pos = padding; - pos.X += stof(f.next_esc(",")) * (float)spacing.X; - pos.Y += stof(f.next_esc(";")) * (float)spacing.Y; - v2s32 geom; - geom.X = (stof(f.next_esc(",")) * (float)spacing.X)-(spacing.X-imgsize.X); - geom.Y = (stof(f.next_esc(";")) * (float)spacing.Y)-(spacing.Y-imgsize.Y); - rect = core::rect(pos.X, pos.Y, pos.X+geom.X, pos.Y+geom.Y); - std::string fimage = f.next_esc(";"); - std::string fname = f.next_esc(";"); - std::string flabel = f.next_esc("]"); - if(bp_set != 2) - errorstream<<"WARNING: invalid use of item_image_button without a size[] element"<idef(); - ItemStack item; - item.deSerialize(fimage, idef); - video::ITexture *texture = idef->getInventoryTexture(item.getDefinition(idef).name, m_gamedef); - std::string tooltip = item.getDefinition(idef).description; - flabel = unescape_string(flabel); - FieldSpec spec = FieldSpec( - narrow_to_wide(fname.c_str()), - narrow_to_wide(flabel.c_str()), - narrow_to_wide(fimage.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.is_button = true; - rect+=basepos-padding; - spec.rect=rect; - if (tooltip!="") - spec.tooltip=tooltip; - m_fields.push_back(spec); - } - else - { - // Ignore others - std::string ts = f.next_esc("]"); - infostream<<"Unknown DrawSpec: type="< rect(0, 0, size.X-padding.X*2, helptext_h); - rect = rect + v2s32(size.X/2 - rect.getWidth()/2, - size.Y-rect.getHeight()-5); + core::rect rect(0, 0, mydata.size.X-padding.X*2, mydata.helptext_h); + rect = rect + v2s32((mydata.size.X/2 - mydata.rect.getWidth()/2) +5, + mydata.size.Y-5-mydata.helptext_h); const wchar_t *text = wgettext("Left click: Move all items, Right click: Move single item"); Environment->addStaticText(text, rect, false, true, this, 256); delete[] text; changeCtype("C"); } // If there's fields, add a Proceed button - if (m_fields.size() && bp_set != 2) + if (m_fields.size() && mydata.bp_set != 2) { // if the size wasn't set by an invsize[] or size[] adjust it now to fit all the fields - rect = core::rect( - screensize.X/2 - 580/2, - screensize.Y/2 - 300/2, - screensize.X/2 + 580/2, - screensize.Y/2 + 240/2+(m_fields.size()*60) + mydata.rect = core::rect( + mydata.screensize.X/2 - 580/2, + mydata.screensize.Y/2 - 300/2, + mydata.screensize.X/2 + 580/2, + mydata.screensize.Y/2 + 240/2+(m_fields.size()*60) ); - DesiredRect = rect; + DesiredRect = mydata.rect; recalculateAbsolutePosition(false); - basepos = getBasePos(); + mydata.basepos = getBasePos(); changeCtype(""); { - v2s32 pos = basepos; + v2s32 pos = mydata.basepos; pos.Y = ((m_fields.size()+2)*60); v2s32 size = DesiredRect.getSize(); - rect = core::rect(size.X/2-70, pos.Y, (size.X/2-70)+140, pos.Y+30); + mydata.rect = core::rect(size.X/2-70, pos.Y, (size.X/2-70)+140, pos.Y+30); wchar_t* text = wgettext("Proceed"); - Environment->addButton(rect, this, 257, text); + Environment->addButton(mydata.rect, this, 257, text); delete[] text; } changeCtype("C"); @@ -684,8 +1614,8 @@ void GUIFormSpecMenu::drawList(const ListDrawSpec &s, int phase) for(s32 i=0; i= ilist->getSize()) + s32 item_i = i + s.start_item_i; + if(item_i >= (s32) ilist->getSize()) break; s32 x = (i%s.geom.X) * spacing.X; s32 y = (i/s.geom.X) * spacing.Y; @@ -804,38 +1734,88 @@ void GUIFormSpecMenu::drawMenu() for(u32 i=0; itsrc()->getTexture(spec.name); - // Image size on screen - core::rect imgrect(0, 0, spec.geom.X, spec.geom.Y); - // Image rectangle on screen - core::rect rect = imgrect + spec.pos; - const video::SColor color(255,255,255,255); - const video::SColor colors[] = {color,color,color,color}; - driver->draw2DImage(texture, rect, - core::rect(core::position2d(0,0), - core::dimension2di(texture->getOriginalSize())), - NULL/*&AbsoluteClippingRect*/, colors, true); + video::ITexture *texture = 0; + + if (m_gamedef != 0) + texture = m_gamedef->tsrc()->getTexture(spec.name); + else + { + texture = driver->getTexture(spec.name.c_str()); + m_Textures.push_back(texture); + } + + if (texture != 0) { + // Image size on screen + core::rect imgrect(0, 0, spec.geom.X, spec.geom.Y); + // Image rectangle on screen + core::rect rect = imgrect + spec.pos; + const video::SColor color(255,255,255,255); + const video::SColor colors[] = {color,color,color,color}; + driver->draw2DImage(texture, rect, + core::rect(core::position2d(0,0), + core::dimension2di(texture->getOriginalSize())), + NULL/*&AbsoluteClippingRect*/, colors, true); + } + else { + errorstream << "GUIFormSpecMenu::drawMenu() Draw backgrounds unable to load texture:" << std::endl; + errorstream << "\t" << spec.name << std::endl; + } } + /* + Draw Boxes + */ + for(u32 i=0; i rect(spec.pos.X,spec.pos.Y, + spec.pos.X + spec.geom.X,spec.pos.Y + spec.geom.Y); + + driver->draw2DRectangle(todraw, rect, 0); + } /* Draw images */ for(u32 i=0; itsrc()->getTexture(spec.name); - // Image size on screen - core::rect imgrect(0, 0, spec.geom.X, spec.geom.Y); - // Image rectangle on screen - core::rect rect = imgrect + spec.pos; - const video::SColor color(255,255,255,255); - const video::SColor colors[] = {color,color,color,color}; - driver->draw2DImage(texture, rect, - core::rect(core::position2d(0,0), - core::dimension2di(texture->getOriginalSize())), - NULL/*&AbsoluteClippingRect*/, colors, true); + video::ITexture *texture = 0; + + if (m_gamedef != 0) + texture = m_gamedef->tsrc()->getTexture(spec.name); + else + { + texture = driver->getTexture(spec.name.c_str()); + m_Textures.push_back(texture); + } + if (texture != 0) { + const core::dimension2d& img_origsize = texture->getOriginalSize(); + // Image size on screen + core::rect imgrect; + + if (spec.scale) + imgrect = core::rect(0,0,spec.geom.X, spec.geom.Y); + else { + + imgrect = core::rect(0,0,img_origsize.Width,img_origsize.Height); + } + // Image rectangle on screen + core::rect rect = imgrect + spec.pos; + const video::SColor color(255,255,255,255); + const video::SColor colors[] = {color,color,color,color}; + driver->draw2DImage(texture, rect, + core::rect(core::position2d(0,0),img_origsize), + NULL/*&AbsoluteClippingRect*/, colors, true); + } + else { + errorstream << "GUIFormSpecMenu::drawMenu() Draw images unable to load texture:" << std::endl; + errorstream << "\t" << spec.name << std::endl; + } } /* @@ -843,6 +1823,9 @@ void GUIFormSpecMenu::drawMenu() */ for(u32 i=0; iidef(); ItemStack item; @@ -1025,24 +2008,77 @@ ItemStack GUIFormSpecMenu::verifySelectedItem() return ItemStack(); } -void GUIFormSpecMenu::acceptInput() +void GUIFormSpecMenu::acceptInput(int eventtype) { if(m_text_dst) { std::map fields; - gui::IGUIElement *e; + for(u32 i=0; igetType() == gui::EGUIET_COMBO_BOX)) { + e = static_cast(element); + } + fields[wide_to_narrow(s.fname.c_str())] = + wide_to_narrow(e->getItem(e->getSelected())); + } + else if (s.ftype == f_TabHeader) { + // no dynamic cast possible due to some distributions shipped + // without rtti support in irrlicht + IGUIElement * element = getElementFromId(s.fid); + gui::IGUITabControl *e = NULL; + if ((element) && (element->getType() == gui::EGUIET_TAB_CONTROL)) { + e = static_cast(element); + } + + if (e != 0) { + std::stringstream ss; + ss << (e->getActiveTab() +1); + fields[wide_to_narrow(s.fname.c_str())] = ss.str(); + } + } + else if (s.ftype == f_CheckBox) { + // no dynamic cast possible due to some distributions shipped + // without rtti support in irrlicht + IGUIElement * element = getElementFromId(s.fid); + gui::IGUICheckBox *e = NULL; + if ((element) && (element->getType() == gui::EGUIET_CHECK_BOX)) { + e = static_cast(element); + } + + if (e != 0) { + if (e->isChecked()) + fields[wide_to_narrow(s.fname.c_str())] = "true"; + else + fields[wide_to_narrow(s.fname.c_str())] = "false"; + } + } else { - e = getElementFromId(s.fid); + IGUIElement* e = getElementFromId(s.fid); if(e != NULL) { fields[wide_to_narrow(s.fname.c_str())] = wide_to_narrow(e->getText()); @@ -1050,6 +2086,7 @@ void GUIFormSpecMenu::acceptInput() } } } + m_text_dst->gotText(fields); } } @@ -1062,13 +2099,20 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) if (event.KeyInput.PressedDown && (kp == EscapeKey || kp == getKeySetting("keymap_inventory"))) { - quitMenu(); + if (m_allowclose) + quitMenu(); + else + m_text_dst->gotText(narrow_to_wide("MenuQuit")); return true; } if(event.KeyInput.Key==KEY_RETURN && event.KeyInput.PressedDown) { acceptInput(); - quitMenu(); + + if (m_allowclose) + quitMenu(); + else + m_text_dst->gotText(narrow_to_wide("KeyEnter")); return true; } } @@ -1360,6 +2404,27 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) } if(event.EventType==EET_GUI_EVENT) { + + if(event.GUIEvent.EventType==gui::EGET_TAB_CHANGED + && isVisible()) + { + // find the element that was clicked + for(u32 i=0; igetID())) + { + s.send = true; + acceptInput(); + s.send = false; + // Restore focus to the full form + Environment->setFocus(this); + return true; + } + } + } if(event.GUIEvent.EventType==gui::EGET_ELEMENT_FOCUS_LOST && isVisible()) { @@ -1371,28 +2436,37 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) return true; } } - if(event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED) + if((event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED) || + (event.GUIEvent.EventType==gui::EGET_CHECKBOX_CHANGED)) { - switch(event.GUIEvent.Caller->getID()) - { - case 257: + unsigned int btn_id = event.GUIEvent.Caller->getID(); + + if (btn_id == 257) { acceptInput(); - quitMenu(); + if (m_allowclose) + quitMenu(); + else + m_text_dst->gotText(narrow_to_wide("ExitButton")); // quitMenu deallocates menu return true; } + // find the element that was clicked for(u32 i=0; igetID()) + if (((s.ftype == f_Button) || (s.ftype == f_CheckBox)) && + (s.fid == event.GUIEvent.Caller->getID())) { s.send = true; acceptInput(); if(s.is_exit){ - quitMenu(); + if (m_allowclose) + quitMenu(); + else + m_text_dst->gotText(narrow_to_wide("ExitButton")); return true; }else{ s.send = false; @@ -1408,13 +2482,103 @@ bool GUIFormSpecMenu::OnEvent(const SEvent& event) if(event.GUIEvent.Caller->getID() > 257) { acceptInput(); - quitMenu(); + if (m_allowclose) + quitMenu(); + else + m_text_dst->gotText(narrow_to_wide("EditBoxEnter")); // quitMenu deallocates menu return true; } } + + if((event.GUIEvent.EventType==gui::EGET_LISTBOX_SELECTED_AGAIN) || + (event.GUIEvent.EventType==gui::EGET_LISTBOX_CHANGED)) + { + int current_id = event.GUIEvent.Caller->getID(); + if(current_id > 257) + { + // find the element that was clicked + for(u32 i=0; isetFocus(this); + } + } + return true; + } + } } return Parent ? Parent->OnEvent(event) : false; } +irr::video::SColor GUIFormSpecMenu::getColor(std::string color,bool& valid_color) { + + if (color == "YLW") { + valid_color = true; + return irr::video::SColor(255,255,255,0); + } + + if (color == "GRN") { + valid_color = true; + return irr::video::SColor(255,34,249,34); + } + + if (color == "LIM") { + valid_color = true; + return irr::video::SColor(255,50,205,50); + } + + if (color == "RED") { + valid_color = true; + return irr::video::SColor(255,255,0,0); + } + + if (color == "ORN") { + valid_color = true; + return irr::video::SColor(255,255,140,0); + } + + if (color == "BLU") { + valid_color = true; + return irr::video::SColor(255,0,0,255); + } + + if (color == "CYN") { + valid_color = true; + return irr::video::SColor(255,0,255,255); + } + + if (color == "BLK") { + valid_color = true; + return irr::video::SColor(255,0,0,0); + } + + if (color == "BRN") { + valid_color = true; + return irr::video::SColor(255,139,69,19); + } + + if (color == "WHT") { + valid_color = true; + return irr::video::SColor(255,255,255,255); + } + + if (color == "GRY") { + valid_color = true; + return irr::video::SColor(255,205,201,201); + } + + valid_color = false; + + return irr::video::SColor(0,0,0,0); +} + -- cgit v1.2.3