Fix formspec replacement handling for in game formspecs

This commit is contained in:
sapier 2014-04-20 02:40:25 +02:00
parent e7ef4f07cb
commit 127f354e7a
4 changed files with 124 additions and 122 deletions

View File

@ -122,13 +122,16 @@ struct TextDestPlayerInventory : public TextDest
struct LocalFormspecHandler : public TextDest struct LocalFormspecHandler : public TextDest
{ {
LocalFormspecHandler(); LocalFormspecHandler();
LocalFormspecHandler(std::string formname) { LocalFormspecHandler(std::string formname) :
m_client(0)
{
m_formname = formname; m_formname = formname;
} }
LocalFormspecHandler(std::string formname,Client *client) { LocalFormspecHandler(std::string formname, Client *client) :
m_client(client)
{
m_formname = formname; m_formname = formname;
m_client = client;
} }
void gotText(std::wstring message) { void gotText(std::wstring message) {
@ -167,25 +170,27 @@ struct LocalFormspecHandler : public TextDest
} }
} }
if (m_formname == "MT_CHAT_MENU") { if (m_formname == "MT_CHAT_MENU") {
assert(m_client != 0);
if ((fields.find("btn_send") != fields.end()) || if ((fields.find("btn_send") != fields.end()) ||
(fields.find("quit") != fields.end())) { (fields.find("quit") != fields.end())) {
if (fields.find("f_text") != fields.end()) { if (fields.find("f_text") != fields.end()) {
if (m_client != 0) { m_client->typeChatMessage(narrow_to_wide(fields["f_text"]));
m_client->typeChatMessage(narrow_to_wide(fields["f_text"]));
}
else {
errorstream << "LocalFormspecHandler::gotText received chat message but m_client is NULL" << std::endl;
}
} }
return; return;
} }
} }
if (m_formname == "MT_DEATH_SCREEN") { if (m_formname == "MT_DEATH_SCREEN") {
assert(m_client != 0);
if ((fields.find("btn_respawn") != fields.end())) { if ((fields.find("btn_respawn") != fields.end())) {
m_client->sendRespawn(); m_client->sendRespawn();
return; return;
} }
if (fields.find("quit") != fields.end()) {
m_client->sendRespawn();
return;
}
} }
errorstream << "LocalFormspecHandler::gotText unhandled >" << m_formname << "< event" << std::endl; errorstream << "LocalFormspecHandler::gotText unhandled >" << m_formname << "< event" << std::endl;
@ -963,34 +968,47 @@ bool nodePlacementPrediction(Client &client,
return false; return false;
} }
static void show_chat_menu(FormspecFormSource* current_formspec, static inline void create_formspec_menu(GUIFormSpecMenu** cur_formspec,
TextDest* current_textdest, IWritableTextureSource* tsrc, InventoryManager *invmgr, IGameDef *gamedef,
IrrlichtDevice * device, Client* client, std::string text) IWritableTextureSource* tsrc, IrrlichtDevice * device,
IFormSource* fs_src, TextDest* txt_dest
) {
if (*cur_formspec == 0) {
*cur_formspec = new GUIFormSpecMenu(device, guiroot, -1, &g_menumgr,
invmgr, gamedef, tsrc, fs_src, txt_dest, cur_formspec );
(*cur_formspec)->doPause = false;
(*cur_formspec)->drop();
}
else {
(*cur_formspec)->setFormSource(fs_src);
(*cur_formspec)->setTextDest(txt_dest);
}
}
static void show_chat_menu(GUIFormSpecMenu** cur_formspec,
InventoryManager *invmgr, IGameDef *gamedef,
IWritableTextureSource* tsrc, IrrlichtDevice * device,
Client* client, std::string text)
{ {
std::string formspec = std::string formspec =
"size[11,5.5,true]" "size[11,5.5,true]"
"field[3,2.35;6,0.5;f_text;;" + text + "]" "field[3,2.35;6,0.5;f_text;;" + text + "]"
"button_exit[4,3;3,0.5;btn_send;" + wide_to_narrow(wstrgettext("Proceed")) + "]" "button_exit[4,3;3,0.5;btn_send;" + wide_to_narrow(wstrgettext("Proceed")) + "]"
; ;
/* Create menu */ /* Create menu */
/* Note: FormspecFormSource and LocalFormspecHandler /* Note: FormspecFormSource and LocalFormspecHandler
* are deleted by guiFormSpecMenu */ * are deleted by guiFormSpecMenu */
current_formspec = new FormspecFormSource(formspec,&current_formspec); FormspecFormSource* fs_src = new FormspecFormSource(formspec);
current_textdest = new LocalFormspecHandler("MT_CHAT_MENU",client); LocalFormspecHandler* txt_dst = new LocalFormspecHandler("MT_CHAT_MENU", client);
GUIFormSpecMenu *menu =
new GUIFormSpecMenu(device, guiroot, -1, create_formspec_menu(cur_formspec, invmgr, gamedef, tsrc, device, fs_src, txt_dst);
&g_menumgr,
NULL, NULL, tsrc);
menu->doPause = false;
menu->setFormSource(current_formspec);
menu->setTextDest(current_textdest);
menu->drop();
} }
static void show_deathscreen(FormspecFormSource* current_formspec, static void show_deathscreen(GUIFormSpecMenu** cur_formspec,
TextDest* current_textdest, IWritableTextureSource* tsrc, InventoryManager *invmgr, IGameDef *gamedef,
IrrlichtDevice * device, Client* client) IWritableTextureSource* tsrc, IrrlichtDevice * device, Client* client)
{ {
std::string formspec = std::string formspec =
std::string("") + std::string("") +
@ -1003,24 +1021,18 @@ static void show_deathscreen(FormspecFormSource* current_formspec,
/* Create menu */ /* Create menu */
/* Note: FormspecFormSource and LocalFormspecHandler /* Note: FormspecFormSource and LocalFormspecHandler
* are deleted by guiFormSpecMenu */ * are deleted by guiFormSpecMenu */
current_formspec = new FormspecFormSource(formspec,&current_formspec); FormspecFormSource* fs_src = new FormspecFormSource(formspec);
current_textdest = new LocalFormspecHandler("MT_DEATH_SCREEN",client); LocalFormspecHandler* txt_dst = new LocalFormspecHandler("MT_DEATH_SCREEN", client);
GUIFormSpecMenu *menu =
new GUIFormSpecMenu(device, guiroot, -1, create_formspec_menu(cur_formspec, invmgr, gamedef, tsrc, device, fs_src, txt_dst);
&g_menumgr,
NULL, NULL, tsrc);
menu->doPause = false;
menu->setFormSource(current_formspec);
menu->setTextDest(current_textdest);
menu->drop();
} }
/******************************************************************************/ /******************************************************************************/
static void show_pause_menu(FormspecFormSource* current_formspec, static void show_pause_menu(GUIFormSpecMenu** cur_formspec,
TextDest* current_textdest, IWritableTextureSource* tsrc, InventoryManager *invmgr, IGameDef *gamedef,
IrrlichtDevice * device, bool singleplayermode) IWritableTextureSource* tsrc, IrrlichtDevice * device,
bool singleplayermode)
{ {
std::string control_text = wide_to_narrow(wstrgettext("Default Controls:\n" std::string control_text = wide_to_narrow(wstrgettext("Default Controls:\n"
"- WASD: move\n" "- WASD: move\n"
"- Space: jump/climb\n" "- Space: jump/climb\n"
@ -1046,7 +1058,7 @@ static void show_pause_menu(FormspecFormSource* current_formspec,
<< wide_to_narrow(wstrgettext("Change Password")) << "]"; << wide_to_narrow(wstrgettext("Change Password")) << "]";
} }
os << "button_exit[4," << (ypos++) << ";3,0.5;btn_sound;" os << "button_exit[4," << (ypos++) << ";3,0.5;btn_sound;"
<< wide_to_narrow(wstrgettext("Sound Volume")) << "]"; << wide_to_narrow(wstrgettext("Sound Volume")) << "]";
os << "button_exit[4," << (ypos++) << ";3,0.5;btn_exit_menu;" os << "button_exit[4," << (ypos++) << ";3,0.5;btn_exit_menu;"
<< wide_to_narrow(wstrgettext("Exit to Menu")) << "]"; << wide_to_narrow(wstrgettext("Exit to Menu")) << "]";
@ -1061,14 +1073,10 @@ static void show_pause_menu(FormspecFormSource* current_formspec,
/* Create menu */ /* Create menu */
/* Note: FormspecFormSource and LocalFormspecHandler * /* Note: FormspecFormSource and LocalFormspecHandler *
* are deleted by guiFormSpecMenu */ * are deleted by guiFormSpecMenu */
current_formspec = new FormspecFormSource(os.str(),&current_formspec); FormspecFormSource* fs_src = new FormspecFormSource(os.str());
current_textdest = new LocalFormspecHandler("MT_PAUSE_MENU"); LocalFormspecHandler* txt_dst = new LocalFormspecHandler("MT_PAUSE_MENU");
GUIFormSpecMenu *menu =
new GUIFormSpecMenu(device, guiroot, -1, &g_menumgr, NULL, NULL, tsrc); create_formspec_menu(cur_formspec, invmgr, gamedef, tsrc, device, fs_src, txt_dst);
menu->doPause = true;
menu->setFormSource(current_formspec);
menu->setTextDest(current_textdest);
menu->drop();
} }
/******************************************************************************/ /******************************************************************************/
@ -1080,8 +1088,7 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
const SubgameSpec &gamespec /* Used for local game */, const SubgameSpec &gamespec /* Used for local game */,
bool simple_singleplayer_mode) bool simple_singleplayer_mode)
{ {
FormspecFormSource* current_formspec = 0; GUIFormSpecMenu* current_formspec = 0;
TextDest* current_textdest = 0;
video::IVideoDriver* driver = device->getVideoDriver(); video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager(); scene::ISceneManager* smgr = device->getSceneManager();
@ -1911,34 +1918,29 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
infostream<<"the_game: " infostream<<"the_game: "
<<"Launching inventory"<<std::endl; <<"Launching inventory"<<std::endl;
GUIFormSpecMenu *menu = PlayerInventoryFormSource* fs_src = new PlayerInventoryFormSource(&client);
new GUIFormSpecMenu(device, guiroot, -1, TextDest* txt_dst = new TextDestPlayerInventory(&client);
&g_menumgr,
&client, gamedef, tsrc); create_formspec_menu(&current_formspec, &client, gamedef, tsrc, device, fs_src, txt_dst);
InventoryLocation inventoryloc; InventoryLocation inventoryloc;
inventoryloc.setCurrentPlayer(); inventoryloc.setCurrentPlayer();
current_formspec->setFormSpec(fs_src->getForm(), inventoryloc);
PlayerInventoryFormSource *src = new PlayerInventoryFormSource(&client);
assert(src);
menu->doPause = false;
menu->setFormSpec(src->getForm(), inventoryloc);
menu->setFormSource(src);
menu->setTextDest(new TextDestPlayerInventory(&client));
menu->drop();
} }
else if(input->wasKeyDown(EscapeKey)) else if(input->wasKeyDown(EscapeKey))
{ {
show_pause_menu(current_formspec, current_textdest, tsrc, device, show_pause_menu(&current_formspec, &client, gamedef, tsrc, device,
simple_singleplayer_mode); simple_singleplayer_mode);
} }
else if(input->wasKeyDown(getKeySetting("keymap_chat"))) else if(input->wasKeyDown(getKeySetting("keymap_chat")))
{ {
show_chat_menu(current_formspec, current_textdest, tsrc, device, &client,""); show_chat_menu(&current_formspec, &client, gamedef, tsrc, device,
&client,"");
} }
else if(input->wasKeyDown(getKeySetting("keymap_cmd"))) else if(input->wasKeyDown(getKeySetting("keymap_cmd")))
{ {
show_chat_menu(current_formspec, current_textdest, tsrc, device, &client,"/"); show_chat_menu(&current_formspec, &client, gamedef, tsrc, device,
&client,"/");
} }
else if(input->wasKeyDown(getKeySetting("keymap_console"))) else if(input->wasKeyDown(getKeySetting("keymap_console")))
{ {
@ -2396,8 +2398,8 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
} }
else if(event.type == CE_DEATHSCREEN) else if(event.type == CE_DEATHSCREEN)
{ {
show_deathscreen(current_formspec, current_textdest, show_deathscreen(&current_formspec, &client, gamedef, tsrc,
tsrc, device, &client); device, &client);
chat_backend.addMessage(L"", L"You died."); chat_backend.addMessage(L"", L"You died.");
@ -2411,29 +2413,14 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
} }
else if (event.type == CE_SHOW_FORMSPEC) else if (event.type == CE_SHOW_FORMSPEC)
{ {
if (current_formspec == 0) FormspecFormSource* fs_src =
{ new FormspecFormSource(*(event.show_formspec.formspec));
/* Create menu */ TextDestPlayerInventory* txt_dst =
/* Note: FormspecFormSource and TextDestPlayerInventory new TextDestPlayerInventory(&client,*(event.show_formspec.formname));
* are deleted by guiFormSpecMenu */
current_formspec = new FormspecFormSource(*(event.show_formspec.formspec),&current_formspec); create_formspec_menu(&current_formspec, &client, gamedef,
current_textdest = new TextDestPlayerInventory(&client,*(event.show_formspec.formname)); tsrc, device, fs_src, txt_dst);
GUIFormSpecMenu *menu =
new GUIFormSpecMenu(device, guiroot, -1,
&g_menumgr,
&client, gamedef, tsrc);
menu->doPause = false;
menu->setFormSource(current_formspec);
menu->setTextDest(current_textdest);
menu->drop();
}
else
{
assert(current_textdest != 0);
/* update menu */
current_textdest->setFormName(*(event.show_formspec.formname));
current_formspec->setForm(*(event.show_formspec.formspec));
}
delete(event.show_formspec.formspec); delete(event.show_formspec.formspec);
delete(event.show_formspec.formname); delete(event.show_formspec.formname);
} }
@ -2986,19 +2973,14 @@ void the_game(bool &kill, bool random_input, InputHandler *input,
InventoryLocation inventoryloc; InventoryLocation inventoryloc;
inventoryloc.setNodeMeta(nodepos); inventoryloc.setNodeMeta(nodepos);
/* Create menu */ NodeMetadataFormSource* fs_src = new NodeMetadataFormSource(
&client.getEnv().getClientMap(), nodepos);
TextDest* txt_dst = new TextDestNodeMetadata(nodepos, &client);
GUIFormSpecMenu *menu = create_formspec_menu(&current_formspec, &client, gamedef,
new GUIFormSpecMenu(device, guiroot, -1, tsrc, device, fs_src, txt_dst);
&g_menumgr,
&client, gamedef, tsrc); current_formspec->setFormSpec(meta->getString("formspec"), inventoryloc);
menu->doPause = false;
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 // Otherwise report right click to server
else else

View File

@ -166,7 +166,7 @@ GUIEngine::GUIEngine( irr::IrrlichtDevice* dev,
rect,false,true,0,-1); rect,false,true,0,-1);
//create formspecsource //create formspecsource
m_formspecgui = new FormspecFormSource("",&m_formspecgui); m_formspecgui = new FormspecFormSource("");
/* Create menu */ /* Create menu */
m_menu = m_menu =
@ -176,12 +176,13 @@ GUIEngine::GUIEngine( irr::IrrlichtDevice* dev,
m_menumanager, m_menumanager,
0 /* &client */, 0 /* &client */,
0 /* gamedef */, 0 /* gamedef */,
m_texture_source); m_texture_source,
m_formspecgui,
m_buttonhandler,
NULL);
m_menu->allowClose(false); m_menu->allowClose(false);
m_menu->lockSize(true,v2u32(800,600)); m_menu->lockSize(true,v2u32(800,600));
m_menu->setFormSource(m_formspecgui);
m_menu->setTextDest(m_buttonhandler);
// Initialize scripting // Initialize scripting

View File

@ -68,20 +68,22 @@ with this program; if not, write to the Free Software Foundation, Inc.,
GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev, GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev,
gui::IGUIElement* parent, s32 id, IMenuManager *menumgr, gui::IGUIElement* parent, s32 id, IMenuManager *menumgr,
InventoryManager *invmgr, IGameDef *gamedef, InventoryManager *invmgr, IGameDef *gamedef,
ISimpleTextureSource *tsrc) : ISimpleTextureSource *tsrc, IFormSource* fsrc, TextDest* tdst,
GUIFormSpecMenu** ext_ptr) :
GUIModalMenu(dev->getGUIEnvironment(), parent, id, menumgr), GUIModalMenu(dev->getGUIEnvironment(), parent, id, menumgr),
m_device(dev), m_device(dev),
m_invmgr(invmgr), m_invmgr(invmgr),
m_gamedef(gamedef), m_gamedef(gamedef),
m_tsrc(tsrc), m_tsrc(tsrc),
m_form_src(NULL),
m_text_dst(NULL),
m_selected_item(NULL), m_selected_item(NULL),
m_selected_amount(0), m_selected_amount(0),
m_selected_dragging(false), m_selected_dragging(false),
m_tooltip_element(NULL), m_tooltip_element(NULL),
m_allowclose(true), m_allowclose(true),
m_lock(false) m_lock(false),
m_form_src(fsrc),
m_text_dst(tdst),
m_ext_ptr(ext_ptr)
{ {
current_keys_pending.key_down = false; current_keys_pending.key_down = false;
current_keys_pending.key_up = false; current_keys_pending.key_up = false;
@ -95,8 +97,18 @@ GUIFormSpecMenu::~GUIFormSpecMenu()
removeChildren(); removeChildren();
delete m_selected_item; delete m_selected_item;
delete m_form_src;
delete m_text_dst; if (m_form_src != NULL) {
delete m_form_src;
}
if (m_text_dst != NULL) {
delete m_text_dst;
}
if (m_ext_ptr != NULL) {
assert(*m_ext_ptr == this);
*m_ext_ptr = NULL;
}
} }
void GUIFormSpecMenu::removeChildren() void GUIFormSpecMenu::removeChildren()

View File

@ -190,7 +190,10 @@ public:
IMenuManager *menumgr, IMenuManager *menumgr,
InventoryManager *invmgr, InventoryManager *invmgr,
IGameDef *gamedef, IGameDef *gamedef,
ISimpleTextureSource *tsrc ISimpleTextureSource *tsrc,
IFormSource* fs_src,
TextDest* txt_dst,
GUIFormSpecMenu** ext_ptr
); );
~GUIFormSpecMenu(); ~GUIFormSpecMenu();
@ -206,12 +209,18 @@ public:
// form_src is deleted by this GUIFormSpecMenu // form_src is deleted by this GUIFormSpecMenu
void setFormSource(IFormSource *form_src) void setFormSource(IFormSource *form_src)
{ {
if (m_form_src != NULL) {
delete m_form_src;
}
m_form_src = form_src; m_form_src = form_src;
} }
// text_dst is deleted by this GUIFormSpecMenu // text_dst is deleted by this GUIFormSpecMenu
void setTextDest(TextDest *text_dst) void setTextDest(TextDest *text_dst)
{ {
if (m_text_dst != NULL) {
delete m_text_dst;
}
m_text_dst = text_dst; m_text_dst = text_dst;
} }
@ -268,8 +277,6 @@ protected:
std::string m_formspec_string; std::string m_formspec_string;
InventoryLocation m_current_inventory_location; InventoryLocation m_current_inventory_location;
IFormSource *m_form_src;
TextDest *m_text_dst;
std::vector<ListDrawSpec> m_inventorylists; std::vector<ListDrawSpec> m_inventorylists;
std::vector<ImageDrawSpec> m_backgrounds; std::vector<ImageDrawSpec> m_backgrounds;
@ -305,6 +312,10 @@ protected:
video::SColor m_slotbg_h; video::SColor m_slotbg_h;
video::SColor m_slotbordercolor; video::SColor m_slotbordercolor;
private: private:
IFormSource* m_form_src;
TextDest* m_text_dst;
GUIFormSpecMenu** m_ext_ptr;
typedef struct { typedef struct {
v2s32 size; v2s32 size;
s32 helptext_h; s32 helptext_h;
@ -360,16 +371,13 @@ private:
class FormspecFormSource: public IFormSource class FormspecFormSource: public IFormSource
{ {
public: public:
FormspecFormSource(std::string formspec,FormspecFormSource** game_formspec) FormspecFormSource(std::string formspec)
{ {
m_formspec = formspec; m_formspec = formspec;
m_game_formspec = game_formspec;
} }
~FormspecFormSource() ~FormspecFormSource()
{ {}
*m_game_formspec = 0;
}
void setForm(std::string formspec) { void setForm(std::string formspec) {
m_formspec = formspec; m_formspec = formspec;
@ -381,7 +389,6 @@ public:
} }
std::string m_formspec; std::string m_formspec;
FormspecFormSource** m_game_formspec;
}; };
#endif #endif