diff options
author | darkrose <lisa@ltmnet.com> | 2012-07-16 02:19:38 +1000 |
---|---|---|
committer | Perttu Ahola <celeron55@gmail.com> | 2012-07-22 17:40:41 +0300 |
commit | 506203345ba2795aa0af68a434f4b77cf50e664a (patch) | |
tree | 51e168ed612bb0bcb7f2e0e2e77242e50bd8e855 /src | |
parent | c259f7c8bd67e38c7be19a90c5113dbf8fd13670 (diff) | |
download | minetest-506203345ba2795aa0af68a434f4b77cf50e664a.tar.gz minetest-506203345ba2795aa0af68a434f4b77cf50e664a.tar.bz2 minetest-506203345ba2795aa0af68a434f4b77cf50e664a.zip |
Implement formspec
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/content_nodemeta.cpp | 8 | ||||
-rw-r--r-- | src/game.cpp | 36 | ||||
-rw-r--r-- | src/guiFormSpecMenu.cpp (renamed from src/guiInventoryMenu.cpp) | 351 | ||||
-rw-r--r-- | src/guiFormSpecMenu.h (renamed from src/guiInventoryMenu.h) | 49 | ||||
-rw-r--r-- | src/guiTextInputMenu.h | 7 | ||||
-rw-r--r-- | src/nodemetadata.h | 9 |
7 files changed, 406 insertions, 56 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 3e9f6d357..a0276cfaa 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -251,7 +251,7 @@ set(minetest_SRCS guiKeyChangeMenu.cpp guiMessageMenu.cpp guiTextInputMenu.cpp - guiInventoryMenu.cpp + guiFormSpecMenu.cpp guiPauseMenu.cpp guiPasswordChange.cpp guiDeathScreen.cpp diff --git a/src/content_nodemeta.cpp b/src/content_nodemeta.cpp index 12c8aa426..0e4c3dd75 100644 --- a/src/content_nodemeta.cpp +++ b/src/content_nodemeta.cpp @@ -63,7 +63,7 @@ static bool content_nodemeta_deserialize_legacy_body( //meta->setString("infotext","\"${text}\""); meta->setString("infotext", std::string("\"") + meta->getString("text") + "\""); - meta->setString("formspec","hack:sign_text_input"); + meta->setString("formspec","field[text;;${text}]"); return false; } else if(id == NODEMETA_CHEST) // ChestNodeMetadata @@ -77,7 +77,7 @@ static bool content_nodemeta_deserialize_legacy_body( } assert(inv->getList("main") && !inv->getList("0")); - meta->setString("formspec","invsize[8,9;]" + meta->setString("formspec","size[8,9]" "list[current_name;main;0,0;8,4;]" "list[current_player;main;0,5;8,4;]"); return false; @@ -94,7 +94,7 @@ static bool content_nodemeta_deserialize_legacy_body( } assert(inv->getList("main") && !inv->getList("0")); - meta->setString("formspec","invsize[8,9;]" + meta->setString("formspec","size[8,9]" "list[current_name;main;0,0;8,4;]" "list[current_player;main;0,5;8,4;]"); return false; @@ -115,7 +115,7 @@ static bool content_nodemeta_deserialize_legacy_body( is>>temp; meta->setString("src_time", ftos((float)temp/10)); - meta->setString("formspec","invsize[8,9;]" + meta->setString("formspec","size[8,9]" "list[current_name;fuel;2,3;1,1;]" "list[current_name;src;2,1;1,1;]" "list[current_name;dst;5,1;2,2;]" diff --git a/src/game.cpp b/src/game.cpp index 347dbf44b..3ba90789a 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -28,7 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "server.h" #include "guiPauseMenu.h" #include "guiPasswordChange.h" -#include "guiInventoryMenu.h" +#include "guiFormSpecMenu.h" #include "guiTextInputMenu.h" #include "guiDeathScreen.h" #include "tool.h" @@ -77,6 +77,10 @@ struct TextDestChat : public TextDest { m_client->typeChatMessage(text); } + void gotText(std::map<std::string, std::string> fields) + { + m_client->typeChatMessage(narrow_to_wide(fields["text"])); + } Client *m_client; }; @@ -88,15 +92,20 @@ struct TextDestNodeMetadata : public TextDest m_p = p; m_client = client; } + // This is deprecated I guess? -celeron55 void gotText(std::wstring text) { std::string ntext = wide_to_narrow(text); - infostream<<"Changing text of a sign node: " - <<ntext<<std::endl; + infostream<<"Submitting 'text' field of node at ("<<m_p.X<<"," + <<m_p.Y<<","<<m_p.Z<<"): "<<ntext<<std::endl; std::map<std::string, std::string> fields; fields["text"] = ntext; m_client->sendNodemetaFields(m_p, "", fields); } + void gotText(std::map<std::string, std::string> fields) + { + m_client->sendNodemetaFields(m_p, "", fields); + } v3s16 m_p; Client *m_client; @@ -139,6 +148,13 @@ public: return ""; return meta->getString("formspec"); } + std::string resolveText(std::string str) + { + NodeMetadata *meta = m_map->getNodeMetadata(m_p); + if(!meta) + return str; + return meta->resolveString(str); + } ClientMap *m_map; v3s16 m_p; @@ -1479,8 +1495,8 @@ void the_game( infostream<<"the_game: " <<"Launching inventory"<<std::endl; - GUIInventoryMenu *menu = - new GUIInventoryMenu(guienv, guiroot, -1, + GUIFormSpecMenu *menu = + new GUIFormSpecMenu(guienv, guiroot, -1, &g_menumgr, &client, gamedef); @@ -1490,7 +1506,7 @@ void the_game( PlayerInventoryFormSource *src = new PlayerInventoryFormSource(&client); assert(src); menu->setFormSpec(src->getForm(), inventoryloc); - menu->setFormSource(new PlayerInventoryFormSource(&client)); + menu->setFormSource(src); menu->drop(); } else if(input->wasKeyDown(EscapeKey)) @@ -2219,7 +2235,8 @@ void the_game( { infostream<<"Ground right-clicked"<<std::endl; - // sign special case, at least until formspec is properly implemented + // Sign special case, at least until formspec is properly implemented. + // Deprecated? if(meta && meta->getString("formspec") == "hack:sign_text_input" && !random_input) { infostream<<"Launching metadata text input"<<std::endl; @@ -2244,14 +2261,15 @@ void the_game( /* Create menu */ - GUIInventoryMenu *menu = - new GUIInventoryMenu(guienv, guiroot, -1, + GUIFormSpecMenu *menu = + new GUIFormSpecMenu(guienv, guiroot, -1, &g_menumgr, &client, gamedef); menu->setFormSpec(meta->getString("formspec"), inventoryloc); menu->setFormSource(new NodeMetadataFormSource( &client.getEnv().getClientMap(), nodepos)); + menu->setTextDest(new TextDestNodeMetadata(nodepos, &client)); menu->drop(); } // Otherwise report right click to server diff --git a/src/guiInventoryMenu.cpp b/src/guiFormSpecMenu.cpp index f60c5b455..02a4fcaad 100644 --- a/src/guiInventoryMenu.cpp +++ b/src/guiFormSpecMenu.cpp @@ -18,7 +18,7 @@ with this program; if not, write to the Free Software Foundation, Inc., */ -#include "guiInventoryMenu.h" +#include "guiFormSpecMenu.h" #include "constants.h" #include "gamedef.h" #include "keycode.h" @@ -33,6 +33,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/string.h" #include "util/numeric.h" +#include "gettext.h" + void drawItemStack(video::IVideoDriver *driver, gui::IGUIFont *font, const ItemStack &item, @@ -120,10 +122,10 @@ void drawItemStack(video::IVideoDriver *driver, } /* - GUIInventoryMenu + GUIFormSpecMenu */ -GUIInventoryMenu::GUIInventoryMenu(gui::IGUIEnvironment* env, +GUIFormSpecMenu::GUIFormSpecMenu(gui::IGUIEnvironment* env, gui::IGUIElement* parent, s32 id, IMenuManager *menumgr, InventoryManager *invmgr, @@ -133,6 +135,7 @@ GUIInventoryMenu::GUIInventoryMenu(gui::IGUIEnvironment* env, m_invmgr(invmgr), m_gamedef(gamedef), m_form_src(NULL), + m_text_dst(NULL), m_selected_item(NULL), m_selected_amount(0), m_selected_dragging(false), @@ -140,7 +143,7 @@ GUIInventoryMenu::GUIInventoryMenu(gui::IGUIEnvironment* env, { } -GUIInventoryMenu::~GUIInventoryMenu() +GUIFormSpecMenu::~GUIFormSpecMenu() { removeChildren(); @@ -148,7 +151,7 @@ GUIInventoryMenu::~GUIInventoryMenu() delete m_form_src; } -void GUIInventoryMenu::removeChildren() +void GUIFormSpecMenu::removeChildren() { const core::list<gui::IGUIElement*> &children = getChildren(); core::list<gui::IGUIElement*> children_copy; @@ -175,7 +178,7 @@ void GUIInventoryMenu::removeChildren() } } -void GUIInventoryMenu::regenerateGui(v2u32 screensize) +void GUIFormSpecMenu::regenerateGui(v2u32 screensize) { // Remove children removeChildren(); @@ -183,24 +186,38 @@ void GUIInventoryMenu::regenerateGui(v2u32 screensize) v2s32 size(100,100); s32 helptext_h = 15; core::rect<s32> rect; + + // Base position of contents of form v2s32 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; /* Convert m_init_draw_spec to m_inventorylists */ m_inventorylists.clear(); m_images.clear(); + m_fields.clear(); Strfnd f(m_formspec_string); while(f.atend() == false) { std::string type = trim(f.next("[")); - if(type == "invsize") + if(type == "invsize" || type == "size") { v2f invsize; invsize.X = stof(f.next(",")); - invsize.Y = stof(f.next(";")); - infostream<<"invsize ("<<invsize.X<<","<<invsize.Y<<")"<<std::endl; - f.next("]"); + if(type == "size") + { + invsize.Y = stof(f.next("]")); + } + else{ + invsize.Y = stof(f.next(";")); + errorstream<<"WARNING: invsize is deprecated, use size"<<std::endl; + f.next("]"); + } + infostream<<"size ("<<invsize.X<<","<<invsize.Y<<")"<<std::endl; padding = v2s32(screensize.Y/40, screensize.Y/40); spacing = v2s32(screensize.Y/12, screensize.Y/13); @@ -218,6 +235,7 @@ void GUIInventoryMenu::regenerateGui(v2u32 screensize) DesiredRect = rect; recalculateAbsolutePosition(false); basepos = getBasePos(); + bp_set = 2; } else if(type == "list") { @@ -239,6 +257,8 @@ void GUIInventoryMenu::regenerateGui(v2u32 screensize) <<", geom=("<<geom.X<<","<<geom.Y<<")" <<std::endl; f.next("]"); + if(bp_set != 2) + errorstream<<"WARNING: invalid use of button without a size[] element"<<std::endl; m_inventorylists.push_back(ListDrawSpec(loc, listname, pos, geom)); } else if(type == "image") @@ -254,8 +274,189 @@ void GUIInventoryMenu::regenerateGui(v2u32 screensize) <<", pos=("<<pos.X<<","<<pos.Y<<")" <<", geom=("<<geom.X<<","<<geom.Y<<")" <<std::endl; + if(bp_set != 2) + errorstream<<"WARNING: invalid use of button without a size[] element"<<std::endl; m_images.push_back(ImageDrawSpec(name, pos, geom)); } + else if(type == "field") + { + std::string fname = f.next(";"); + std::string flabel = f.next(";"); + + if(fname.find(",") == std::string::npos && flabel.find(",") == std::string::npos) + { + if(!bp_set) + { + rect = core::rect<s32>( + 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 field in inventory"<<std::endl; + + v2s32 pos = basepos; + pos.Y = ((m_fields.size()+2)*60); + v2s32 size = DesiredRect.getSize(); + rect = core::rect<s32>(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); + pos.Y += (stof(flabel.substr(flabel.find(",")+1)) * (float)imgsize.Y)/2; + + rect = core::rect<s32>(pos.X, pos.Y-15, pos.X+geom.X, pos.Y+15); + + fname = f.next(";"); + flabel = f.next(";"); + if(bp_set != 2) + errorstream<<"WARNING: invalid use of positioned field without a size[] element"<<std::endl; + + } + + std::string odefault = f.next("]"); + std::string fdefault; + + // fdefault may contain a variable reference, which + // needs to be resolved from the node metadata + if(m_form_src) + fdefault = m_form_src->resolveText(odefault); + else + fdefault = odefault; + + 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 and no label, label and no field, label and field + if (flabel == "") + { + spec.send = true; + gui::IGUIElement *e = Environment->addEditBox(spec.fdefault.c_str(), rect, true, this, spec.fid); + Environment->setFocus(e); + + irr::SEvent evt; + evt.EventType = EET_KEY_INPUT_EVENT; + evt.KeyInput.Key = KEY_END; + evt.KeyInput.PressedDown = true; + e->OnEvent(evt); + } + else if (fname == "") + { + // set 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::IGUIElement *e = Environment->addEditBox(spec.fdefault.c_str(), rect, true, this, spec.fid); + Environment->setFocus(e); + rect.UpperLeftCorner.Y -= 15; + rect.LowerRightCorner.Y -= 15; + Environment->addStaticText(spec.flabel.c_str(), rect, false, true, this, 0); + + irr::SEvent evt; + evt.EventType = EET_KEY_INPUT_EVENT; + evt.KeyInput.Key = KEY_END; + evt.KeyInput.PressedDown = true; + e->OnEvent(evt); + } + + m_fields.push_back(spec); + } + else if(type == "label") + { + v2s32 pos; + pos.X = stof(f.next(",")) * (float)spacing.X; + pos.Y = stof(f.next(";")) * (float)spacing.Y; + + rect = core::rect<s32>(pos.X, pos.Y+((imgsize.Y/2)-15), pos.X+300, pos.Y+((imgsize.Y/2)+15)); + + std::string flabel = f.next("]"); + if(bp_set != 2) + errorstream<<"WARNING: invalid use of label without a size[] element"<<std::endl; + + 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") + { + v2s32 pos; + pos.X = stof(f.next(",")) * (float)spacing.X; + pos.Y = stof(f.next(";")) * (float)spacing.Y; + v2s32 geom; + geom.X = (stof(f.next(",")) * (float)spacing.X)-(spacing.X-imgsize.X); + pos.Y += (stof(f.next(";")) * (float)imgsize.Y)/2; + + rect = core::rect<s32>(pos.X, pos.Y-15, pos.X+geom.X, pos.Y+15); + + std::string fname = f.next(";"); + std::string flabel = f.next("]"); + if(bp_set != 2) + errorstream<<"WARNING: invalid use of button without a size[] element"<<std::endl; + + FieldSpec spec = FieldSpec( + narrow_to_wide(fname.c_str()), + narrow_to_wide(flabel.c_str()), + narrow_to_wide(""), + 258+m_fields.size() + ); + spec.is_button = true; + Environment->addButton(rect, this, spec.fid, spec.flabel.c_str()); + m_fields.push_back(spec); + } + else if(type == "image_button") + { + v2s32 pos; + pos.X = stof(f.next(",")) * (float)spacing.X; + pos.Y = stof(f.next(";")) * (float)spacing.Y; + v2s32 geom; + geom.X = (stof(f.next(",")) * (float)spacing.X)-(spacing.X-imgsize.X); + geom.Y = (stof(f.next(";")) * (float)spacing.Y)-(spacing.Y-imgsize.Y); + + rect = core::rect<s32>(pos.X, pos.Y, pos.X+geom.X, pos.Y+geom.Y); + + std::string fimage = f.next(";"); + std::string fname = f.next(";"); + std::string flabel = f.next("]"); + if(bp_set != 2) + errorstream<<"WARNING: invalid use of image_button without a size[] element"<<std::endl; + + 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() + ); + spec.is_button = true; + + video::ITexture *texture = m_gamedef->tsrc()->getTextureRaw(fimage); + gui::IGUIButton *e = Environment->addButton(rect, this, spec.fid, spec.flabel.c_str()); + e->setImage(texture); + e->setPressedImage(texture); + e->setScaleImage(true); + + m_fields.push_back(spec); + } else { // Ignore others @@ -265,16 +466,44 @@ void GUIInventoryMenu::regenerateGui(v2u32 screensize) } } - // Add children + // If there's inventory, put the usage string at the bottom + if (m_inventorylists.size()) { + changeCtype(""); core::rect<s32> rect(0, 0, size.X-padding.X*2, helptext_h); rect = rect + v2s32(size.X/2 - rect.getWidth()/2, size.Y-rect.getHeight()-5); - const wchar_t *text = - L"Left click: Move all items, Right click: Move single item"; + const wchar_t *text = wgettext("Left click: Move all items, Right click: Move single item"); Environment->addStaticText(text, rect, false, true, this, 256); + changeCtype("C"); + } + // If there's fields, add a Proceed button + if (m_fields.size() && 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<s32>( + screensize.X/2 - 580/2, + screensize.Y/2 - 300/2, + screensize.X/2 + 580/2, + screensize.Y/2 + 240/2+(m_fields.size()*60) + ); + DesiredRect = rect; + recalculateAbsolutePosition(false); + basepos = getBasePos(); - // Add tooltip + changeCtype(""); + { + v2s32 pos = basepos; + pos.Y = ((m_fields.size()+2)*60); + + v2s32 size = DesiredRect.getSize(); + rect = core::rect<s32>(size.X/2-70, pos.Y, (size.X/2-70)+140, pos.Y+30); + Environment->addButton(rect, this, 257, wgettext("Proceed")); + } + changeCtype("C"); + } + // Add tooltip + { // Note: parent != this so that the tooltip isn't clipped by the menu rectangle m_tooltip_element = Environment->addStaticText(L"",core::rect<s32>(0,0,110,18)); m_tooltip_element->enableOverrideColor(true); @@ -287,7 +516,7 @@ void GUIInventoryMenu::regenerateGui(v2u32 screensize) } } -GUIInventoryMenu::ItemSpec GUIInventoryMenu::getItemAtPos(v2s32 p) const +GUIFormSpecMenu::ItemSpec GUIFormSpecMenu::getItemAtPos(v2s32 p) const { core::rect<s32> imgrect(0,0,imgsize.X,imgsize.Y); @@ -311,7 +540,7 @@ GUIInventoryMenu::ItemSpec GUIInventoryMenu::getItemAtPos(v2s32 p) const return ItemSpec(InventoryLocation(), "", -1); } -void GUIInventoryMenu::drawList(const ListDrawSpec &s, int phase) +void GUIFormSpecMenu::drawList(const ListDrawSpec &s, int phase) { video::IVideoDriver* driver = Environment->getVideoDriver(); @@ -323,7 +552,7 @@ void GUIInventoryMenu::drawList(const ListDrawSpec &s, int phase) Inventory *inv = m_invmgr->getInventory(s.inventoryloc); if(!inv){ - infostream<<"GUIInventoryMenu::drawList(): WARNING: " + infostream<<"GUIFormSpecMenu::drawList(): WARNING: " <<"The inventory location " <<"\""<<s.inventoryloc.dump()<<"\" doesn't exist" <<std::endl; @@ -331,7 +560,7 @@ void GUIInventoryMenu::drawList(const ListDrawSpec &s, int phase) } InventoryList *ilist = inv->getList(s.listname); if(!ilist){ - infostream<<"GUIInventoryMenu::drawList(): WARNING: " + infostream<<"GUIFormSpecMenu::drawList(): WARNING: " <<"The inventory list \""<<s.listname<<"\" @ \"" <<s.inventoryloc.dump()<<"\" doesn't exist" <<std::endl; @@ -404,7 +633,7 @@ void GUIInventoryMenu::drawList(const ListDrawSpec &s, int phase) } } -void GUIInventoryMenu::drawSelectedItem() +void GUIFormSpecMenu::drawSelectedItem() { if(!m_selected_item) return; @@ -429,7 +658,7 @@ void GUIInventoryMenu::drawSelectedItem() drawItemStack(driver, font, stack, rect, NULL, m_gamedef); } -void GUIInventoryMenu::drawMenu() +void GUIFormSpecMenu::drawMenu() { if(m_form_src){ std::string newform = m_form_src->getForm(); @@ -491,7 +720,7 @@ void GUIInventoryMenu::drawMenu() gui::IGUIElement::draw(); } -void GUIInventoryMenu::updateSelectedItem() +void GUIFormSpecMenu::updateSelectedItem() { // If the selected stack has become empty for some reason, deselect it. // If the selected stack has become smaller, adjust m_selected_amount. @@ -558,7 +787,38 @@ void GUIInventoryMenu::updateSelectedItem() } } -bool GUIInventoryMenu::OnEvent(const SEvent& event) +void GUIFormSpecMenu::acceptInput() +{ + if(m_text_dst) + { + std::map<std::string, std::string> fields; + gui::IGUIElement *e; + for(u32 i=0; i<m_fields.size(); i++) + { + const FieldSpec &s = m_fields[i]; + if(s.send) + { + if(s.is_button) + { + fields[wide_to_narrow(s.fname.c_str())] = wide_to_narrow(s.flabel.c_str()); + } + else + { + e = getElementFromId(s.fid); + if(e != NULL) + { + fields[wide_to_narrow(s.fname.c_str())] = wide_to_narrow(e->getText()); + } + } + } + } + m_text_dst->gotText(fields); + delete m_text_dst; + m_text_dst = NULL; + } +} + +bool GUIFormSpecMenu::OnEvent(const SEvent& event) { if(event.EventType==EET_KEY_INPUT_EVENT) { @@ -569,6 +829,12 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event) quitMenu(); return true; } + if(event.KeyInput.Key==KEY_RETURN && event.KeyInput.PressedDown) + { + acceptInput(); + quitMenu(); + return true; + } } if(event.EventType==EET_MOUSE_INPUT_EVENT && event.MouseInput.Event == EMIE_MOUSE_MOVED) @@ -860,7 +1126,7 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event) { if(!canTakeFocus(event.GUIEvent.Element)) { - infostream<<"GUIInventoryMenu: Not allowing focus change." + infostream<<"GUIFormSpecMenu: Not allowing focus change." <<std::endl; // Returning true disables focus change return true; @@ -868,15 +1134,38 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event) } if(event.GUIEvent.EventType==gui::EGET_BUTTON_CLICKED) { - /*switch(event.GUIEvent.Caller->getID()) + switch(event.GUIEvent.Caller->getID()) { - case 256: // continue - setVisible(false); - break; - case 257: // exit - dev->closeDevice(); - break; - }*/ + case 257: + acceptInput(); + quitMenu(); + // quitMenu deallocates menu + return true; + } + // find the element that was clicked + for(u32 i=0; i<m_fields.size(); i++) + { + FieldSpec &s = m_fields[i]; + // if its a button, set the send field so + // lua knows which button was pressed + if (s.is_button && s.fid == event.GUIEvent.Caller->getID()) + { + s.send = true; + acceptInput(); + quitMenu(); + return true; + } + } + } + if(event.GUIEvent.EventType==gui::EGET_EDITBOX_ENTER) + { + if(event.GUIEvent.Caller->getID() > 257) + { + acceptInput(); + quitMenu(); + // quitMenu deallocates menu + return true; + } } } diff --git a/src/guiInventoryMenu.h b/src/guiFormSpecMenu.h index 5613db356..a60629153 100644 --- a/src/guiInventoryMenu.h +++ b/src/guiFormSpecMenu.h @@ -29,11 +29,21 @@ with this program; if not, write to the Free Software Foundation, Inc., class IGameDef; class InventoryManager; +struct TextDest +{ + virtual ~TextDest() {}; + // This is deprecated I guess? -celeron55 + virtual void gotText(std::wstring text) = 0; + virtual void gotText(std::map<std::string, std::string> fields) = 0; +}; + class IFormSource { public: virtual ~IFormSource(){} virtual std::string getForm() = 0; + // Fill in variables in field text + virtual std::string resolveText(std::string str){ return str; } }; void drawItemStack(video::IVideoDriver *driver, @@ -43,7 +53,7 @@ void drawItemStack(video::IVideoDriver *driver, const core::rect<s32> *clip, IGameDef *gamedef); -class GUIInventoryMenu : public GUIModalMenu +class GUIFormSpecMenu : public GUIModalMenu { struct ItemSpec { @@ -106,15 +116,37 @@ class GUIInventoryMenu : public GUIModalMenu v2s32 pos; v2s32 geom; }; + + struct FieldSpec + { + FieldSpec() + { + } + FieldSpec(const std::wstring name, const std::wstring label, const std::wstring fdeflt, int id): + fname(name), + flabel(label), + fdefault(fdeflt), + fid(id) + { + send = false; + is_button = false; + } + std::wstring fname; + std::wstring flabel; + std::wstring fdefault; + int fid; + bool send; + bool is_button; + }; public: - GUIInventoryMenu(gui::IGUIEnvironment* env, + GUIFormSpecMenu(gui::IGUIEnvironment* env, gui::IGUIElement* parent, s32 id, IMenuManager *menumgr, InventoryManager *invmgr, IGameDef *gamedef ); - ~GUIInventoryMenu(); + ~GUIFormSpecMenu(); void setFormSpec(const std::string &formspec_string, InventoryLocation current_inventory_location) @@ -124,12 +156,18 @@ public: regenerateGui(m_screensize_old); } - // form_src is deleted by this GUIInventoryMenu + // form_src is deleted by this GUIFormSpecMenu void setFormSource(IFormSource *form_src) { m_form_src = form_src; } + // text_dst is deleted by this GUIFormSpecMenu + void setTextDest(TextDest *text_dst) + { + m_text_dst = text_dst; + } + void removeChildren(); /* Remove and re-add (or reposition) stuff @@ -142,6 +180,7 @@ public: void drawMenu(); void updateSelectedItem(); + void acceptInput(); bool OnEvent(const SEvent& event); protected: @@ -160,9 +199,11 @@ protected: std::string m_formspec_string; InventoryLocation m_current_inventory_location; IFormSource *m_form_src; + TextDest *m_text_dst; core::array<ListDrawSpec> m_inventorylists; core::array<ImageDrawSpec> m_images; + core::array<FieldSpec> m_fields; ItemSpec *m_selected_item; u32 m_selected_amount; diff --git a/src/guiTextInputMenu.h b/src/guiTextInputMenu.h index 76417894b..1a55525c9 100644 --- a/src/guiTextInputMenu.h +++ b/src/guiTextInputMenu.h @@ -22,14 +22,9 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "irrlichttypes_extrabloated.h" #include "modalMenu.h" +#include "guiFormSpecMenu.h" #include <string> -struct TextDest -{ - virtual void gotText(std::wstring text) = 0; - virtual ~TextDest() {}; -}; - class GUITextInputMenu : public GUIModalMenu { public: diff --git a/src/nodemetadata.h b/src/nodemetadata.h index 24779a1ea..262b64d74 100644 --- a/src/nodemetadata.h +++ b/src/nodemetadata.h @@ -55,7 +55,7 @@ public: i = m_stringvars.find(name); if(i == m_stringvars.end()) return ""; - return i->second; + return resolveString(i->second); } void setString(const std::string &name, const std::string &var) { @@ -64,6 +64,13 @@ public: else m_stringvars[name] = var; } + // support variable names in values + std::string resolveString(const std::string &str) const + { + if(str.substr(0,2) == "${" && str[str.length()-1] == '}') + return resolveString(getString(str.substr(2,str.length()-3))); + return str; + } std::map<std::string, std::string> getStrings() const { return m_stringvars; |