From 3c4734d69a44aea133e5bd7df66a5dedb87785fb Mon Sep 17 00:00:00 2001 From: Kahrl Date: Tue, 20 Aug 2013 22:38:14 +0200 Subject: Change mainmenu texture handling + small misc changes Texture names must now be escaped in formspec elements image[], background[], image_button[], image_button_exit[]. Instead of special-case handling of texture loading (and unloading which was missing) in guiFormSpecMenu.cpp, use the newly created ISimpleTextureSource interface which is a minimal subset of ITextureSource. There is an implementation of this interface used by GUIEngine (MenuTextureSource). Fix an off-by-one bug in unescape_string; it caused requests for a texture called "\0". --- src/game.cpp | 6 ++--- src/guiEngine.cpp | 48 ++++++++++++++++++++++++++++++++++++++-- src/guiEngine.h | 55 +++++++++++++++++++++++++++++++++++++++------- src/guiFormSpecMenu.cpp | 58 ++++++++++++------------------------------------- src/guiFormSpecMenu.h | 7 +++--- src/tile.h | 46 ++++++++++++++++++++------------------- src/util/string.h | 2 +- 7 files changed, 139 insertions(+), 83 deletions(-) (limited to 'src') diff --git a/src/game.cpp b/src/game.cpp index 5d8365781..f313ae28f 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1720,7 +1720,7 @@ void the_game( GUIFormSpecMenu *menu = new GUIFormSpecMenu(device, guiroot, -1, &g_menumgr, - &client, gamedef); + &client, gamedef, tsrc); InventoryLocation inventoryloc; inventoryloc.setCurrentPlayer(); @@ -2259,7 +2259,7 @@ void the_game( GUIFormSpecMenu *menu = new GUIFormSpecMenu(device, guiroot, -1, &g_menumgr, - &client, gamedef); + &client, gamedef, tsrc); menu->setFormSource(current_formspec); menu->setTextDest(current_textdest); menu->drop(); @@ -2755,7 +2755,7 @@ void the_game( GUIFormSpecMenu *menu = new GUIFormSpecMenu(device, guiroot, -1, &g_menumgr, - &client, gamedef); + &client, gamedef, tsrc); menu->setFormSpec(meta->getString("formspec"), inventoryloc); menu->setFormSource(new NodeMetadataFormSource( diff --git a/src/guiEngine.cpp b/src/guiEngine.cpp index f00cd039c..547f393a4 100644 --- a/src/guiEngine.cpp +++ b/src/guiEngine.cpp @@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "guiMainMenu.h" #include "sound.h" #include "sound_openal.h" +#include "clouds.h" #include #include @@ -36,6 +37,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #endif +/******************************************************************************/ +/** TextDestGuiEngine */ /******************************************************************************/ TextDestGuiEngine::TextDestGuiEngine(GUIEngine* engine) { @@ -54,6 +57,38 @@ void TextDestGuiEngine::gotText(std::wstring text) m_engine->getScriptIface()->handleMainMenuEvent(wide_to_narrow(text)); } +/******************************************************************************/ +/** MenuTextureSource */ +/******************************************************************************/ +MenuTextureSource::MenuTextureSource(video::IVideoDriver *driver) +{ + m_driver = driver; +} + +/******************************************************************************/ +MenuTextureSource::~MenuTextureSource() +{ + for (std::set::iterator it = m_to_delete.begin(); + it != m_to_delete.end(); ++it) { + const char *tname = (*it).c_str(); + video::ITexture *texture = m_driver->getTexture(tname); + m_driver->removeTexture(texture); + } +} + +/******************************************************************************/ +video::ITexture* MenuTextureSource::getTexture(const std::string &name, u32 *id) +{ + if(id) + *id = 0; + if(name.empty()) + return NULL; + m_to_delete.insert(name); + return m_driver->getTexture(name.c_str()); +} + +/******************************************************************************/ +/** MenuMusicFetcher */ /******************************************************************************/ void MenuMusicFetcher::fetchSounds(const std::string &name, std::set &dst_paths, @@ -74,6 +109,8 @@ void MenuMusicFetcher::fetchSounds(const std::string &name, dst_paths.insert(base + DIR_DELIM + name + "."+itos(i)+".ogg"); } +/******************************************************************************/ +/** GUIEngine */ /******************************************************************************/ GUIEngine::GUIEngine( irr::IrrlichtDevice* dev, gui::IGUIElement* parent, @@ -86,6 +123,7 @@ GUIEngine::GUIEngine( irr::IrrlichtDevice* dev, m_menumanager(menumgr), m_smgr(smgr), m_data(data), + m_texture_source(NULL), m_sound_manager(NULL), m_formspecgui(0), m_buttonhandler(0), @@ -105,6 +143,9 @@ GUIEngine::GUIEngine( irr::IrrlichtDevice* dev, // is deleted by guiformspec! m_buttonhandler = new TextDestGuiEngine(this); + //create texture source + m_texture_source = new MenuTextureSource(m_device->getVideoDriver()); + //create soundmanager MenuMusicFetcher soundfetcher; #if USE_SOUND @@ -132,7 +173,8 @@ GUIEngine::GUIEngine( irr::IrrlichtDevice* dev, -1, m_menumanager, 0 /* &client */, - 0 /* gamedef */); + 0 /* gamedef */, + m_texture_source); m_menu->allowClose(false); m_menu->lockSize(true,v2u32(800,600)); @@ -264,11 +306,13 @@ GUIEngine::~GUIEngine() m_irr_toplefttext->setText(L""); - //initialize texture pointers + //clean up texture pointers for (unsigned int i = 0; i < TEX_LAYER_MAX; i++) { if (m_textures[i] != 0) driver->removeTexture(m_textures[i]); } + + delete m_texture_source; if (m_cloud.clouds) m_cloud.clouds->drop(); diff --git a/src/guiEngine.h b/src/guiEngine.h index 6b7d3b6ed..484459395 100644 --- a/src/guiEngine.h +++ b/src/guiEngine.h @@ -25,17 +25,13 @@ with this program; if not, write to the Free Software Foundation, Inc., /******************************************************************************/ #include "irrlichttypes.h" #include "modalMenu.h" -#include "clouds.h" #include "guiFormSpecMenu.h" #include "sound.h" +#include "tile.h" /******************************************************************************/ /* Typedefs and macros */ /******************************************************************************/ -#define MAX_MENUBAR_BTN_COUNT 10 -#define MAX_MENUBAR_BTN_ID 256 -#define MIN_MENUBAR_BTN_ID (MAX_MENUBAR_BTN_ID - MAX_MENUBAR_BTN_COUNT) - /** texture layer ids */ typedef enum { TEX_LAYER_BACKGROUND = 0, @@ -50,8 +46,8 @@ typedef enum { /******************************************************************************/ class GUIEngine; class MainMenuScripting; +class Clouds; struct MainMenuData; -struct SimpleSoundSpec; /******************************************************************************/ /* declarations */ @@ -66,6 +62,7 @@ public: * @param engine the engine data is transmitted for further processing */ TextDestGuiEngine(GUIEngine* engine); + /** * receive fields transmitted by guiFormSpecMenu * @param fields map containing formspec field elements currently active @@ -77,18 +74,58 @@ public: * @param text textual representation of event */ void gotText(std::wstring text); + private: /** target to transmit data to */ GUIEngine* m_engine; }; +/** GUIEngine specific implementation of ISimpleTextureSource */ +class MenuTextureSource : public ISimpleTextureSource +{ +public: + /** + * default constructor + * @param driver the video driver to load textures from + */ + MenuTextureSource(video::IVideoDriver *driver); + + /** + * destructor, removes all loaded textures + */ + virtual ~MenuTextureSource(); + + /** + * get a texture, loading it if required + * @param name path to the texture + * @param id receives the texture ID, always 0 in this implementation + */ + video::ITexture* getTexture(const std::string &name, u32 *id = NULL); + +private: + /** driver to get textures from */ + video::IVideoDriver *m_driver; + /** set of texture names to delete */ + std::set m_to_delete; +}; + +/** GUIEngine specific implementation of OnDemandSoundFetcher */ class MenuMusicFetcher: public OnDemandSoundFetcher { - std::set m_fetched; public: + /** + * get sound file paths according to sound name + * @param name sound name + * @param dst_paths receives possible paths to sound files + * @param dst_datas receives binary sound data (not used here) + */ void fetchSounds(const std::string &name, std::set &dst_paths, std::set &dst_datas); + +private: + /** set of fetched sound names */ + std::set m_fetched; }; /** implementation of main menu based uppon formspecs */ @@ -150,6 +187,8 @@ private: scene::ISceneManager* m_smgr; /** pointer to data beeing transfered back to main game handling */ MainMenuData* m_data; + /** pointer to texture source */ + ISimpleTextureSource* m_texture_source; /** pointer to soundmanager*/ ISoundManager* m_sound_manager; @@ -167,7 +206,7 @@ private: bool m_startgame; /** scripting interface */ - MainMenuScripting* m_script; + MainMenuScripting* m_script; /** script basefolder */ std::string m_scriptdir; diff --git a/src/guiFormSpecMenu.cpp b/src/guiFormSpecMenu.cpp index bc33143a4..28cb6740e 100644 --- a/src/guiFormSpecMenu.cpp +++ b/src/guiFormSpecMenu.cpp @@ -69,12 +69,14 @@ GUIFormSpecMenu::GUIFormSpecMenu(irr::IrrlichtDevice* dev, gui::IGUIElement* parent, s32 id, IMenuManager *menumgr, InventoryManager *invmgr, - IGameDef *gamedef + IGameDef *gamedef, + ISimpleTextureSource *tsrc ): GUIModalMenu(dev->getGUIEnvironment(), parent, id, menumgr), m_device(dev), m_invmgr(invmgr), m_gamedef(gamedef), + m_tsrc(tsrc), m_form_src(NULL), m_text_dst(NULL), m_selected_item(NULL), @@ -483,7 +485,7 @@ void GUIFormSpecMenu::parseImage(parserData* data,std::string element) { if (parts.size() == 3) { std::vector v_pos = split(parts[0],','); std::vector v_geom = split(parts[1],','); - std::string name = parts[2]; + std::string name = unescape_string(parts[2]); MY_CHECKPOS("image",0); MY_CHECKGEOM("image",1); @@ -504,7 +506,7 @@ void GUIFormSpecMenu::parseImage(parserData* data,std::string element) { if (parts.size() == 2) { std::vector v_pos = split(parts[0],','); - std::string name = parts[1]; + std::string name = unescape_string(parts[1]); MY_CHECKPOS("image",0); @@ -605,7 +607,7 @@ void GUIFormSpecMenu::parseBackground(parserData* data,std::string element) { if (parts.size() == 3) { std::vector v_pos = split(parts[0],','); std::vector v_geom = split(parts[1],','); - std::string name = parts[2]; + std::string name = unescape_string(parts[2]); MY_CHECKPOS("background",0); MY_CHECKGEOM("background",1); @@ -769,11 +771,6 @@ void GUIFormSpecMenu::parseDropDown(parserData* data,std::string element) { 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; } @@ -1149,6 +1146,8 @@ void GUIFormSpecMenu::parseImageButton(parserData* data,std::string element,std: if(data->bp_set != 2) errorstream<<"WARNING: invalid use of item_image_button without a size[] element"<tsrc()->getTexture(image_name); - if ((parts.size() == 8)) { - pressed_texture = m_gamedef->tsrc()->getTexture(pressed_image_name); - } - } else { - if (fs::PathExists(image_name)) { - texture = Environment->getVideoDriver()->getTexture(image_name.c_str()); - m_Textures.push_back(texture); - } - if (fs::PathExists(pressed_image_name)) { - pressed_texture = Environment->getVideoDriver()->getTexture(pressed_image_name.c_str()); - m_Textures.push_back(pressed_texture); - } - } - if (parts.size() < 8) + texture = m_tsrc->getTexture(image_name); + if (parts.size() == 8) + pressed_texture = m_tsrc->getTexture(pressed_image_name); + else pressed_texture = texture; gui::IGUIButton *e = Environment->addButton(rect, this, spec.fid, spec.flabel.c_str()); @@ -1797,15 +1782,7 @@ void GUIFormSpecMenu::drawMenu() for(u32 i=0; itsrc()->getTexture(spec.name); - else - { - texture = driver->getTexture(spec.name.c_str()); - m_Textures.push_back(texture); - } + video::ITexture *texture = m_tsrc->getTexture(spec.name); if (texture != 0) { // Image size on screen @@ -1847,15 +1824,8 @@ void GUIFormSpecMenu::drawMenu() for(u32 i=0; igetTexture(spec.name); - 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 diff --git a/src/guiFormSpecMenu.h b/src/guiFormSpecMenu.h index 73c21b72d..c244e458f 100644 --- a/src/guiFormSpecMenu.h +++ b/src/guiFormSpecMenu.h @@ -30,6 +30,7 @@ with this program; if not, write to the Free Software Foundation, Inc., class IGameDef; class InventoryManager; +class ISimpleTextureSource; typedef enum { f_Button, @@ -176,7 +177,8 @@ public: gui::IGUIElement* parent, s32 id, IMenuManager *menumgr, InventoryManager *invmgr, - IGameDef *gamedef + IGameDef *gamedef, + ISimpleTextureSource *tsrc ); ~GUIFormSpecMenu(); @@ -245,6 +247,7 @@ protected: irr::IrrlichtDevice* m_device; InventoryManager *m_invmgr; IGameDef *m_gamedef; + ISimpleTextureSource *m_tsrc; std::string m_formspec_string; InventoryLocation m_current_inventory_location; @@ -302,8 +305,6 @@ private: bool key_escape; } fs_key_pendig; - std::vector m_Textures; - fs_key_pendig current_keys_pending; // Determine whether listbox click was double click diff --git a/src/tile.h b/src/tile.h index 23c214350..90e180a48 100644 --- a/src/tile.h +++ b/src/tile.h @@ -82,22 +82,27 @@ struct TextureFromMeshParams TextureSource creates and caches textures. */ -class ITextureSource +class ISimpleTextureSource +{ +public: + ISimpleTextureSource(){} + virtual ~ISimpleTextureSource(){} + virtual video::ITexture* getTexture( + const std::string &name, u32 *id = NULL) = 0; +}; + +class ITextureSource : public ISimpleTextureSource { public: ITextureSource(){} virtual ~ITextureSource(){} - virtual u32 getTextureId(const std::string &name){return 0;} - virtual u32 getTextureIdDirect(const std::string &name){return 0;} - virtual std::string getTextureName(u32 id){return "";} - virtual video::ITexture* getTexture(u32 id){return NULL;} + virtual u32 getTextureId(const std::string &name)=0; + virtual u32 getTextureIdDirect(const std::string &name)=0; + virtual std::string getTextureName(u32 id)=0; + virtual video::ITexture* getTexture(u32 id)=0; virtual video::ITexture* getTexture( - const std::string &name, u32 *id = NULL){ - if(id) *id = 0; - return NULL; - } - virtual IrrlichtDevice* getDevice() - {return NULL;} + const std::string &name, u32 *id = NULL)=0; + virtual IrrlichtDevice* getDevice()=0; virtual bool isKnownSourceImage(const std::string &name)=0; virtual video::ITexture* generateTextureFromMesh( const TextureFromMeshParams ¶ms)=0; @@ -108,23 +113,20 @@ class IWritableTextureSource : public ITextureSource public: IWritableTextureSource(){} virtual ~IWritableTextureSource(){} - virtual u32 getTextureId(const std::string &name){return 0;} - virtual u32 getTextureIdDirect(const std::string &name){return 0;} - virtual std::string getTextureName(u32 id){return "";} - virtual video::ITexture* getTexture(u32 id){return NULL;} + virtual u32 getTextureId(const std::string &name)=0; + virtual u32 getTextureIdDirect(const std::string &name)=0; + virtual std::string getTextureName(u32 id)=0; + virtual video::ITexture* getTexture(u32 id)=0; virtual video::ITexture* getTexture( - const std::string &name, u32 *id = NULL){ - if(id) *id = 0; - return NULL; - } - virtual IrrlichtDevice* getDevice(){return NULL;} + const std::string &name, u32 *id = NULL)=0; + virtual IrrlichtDevice* getDevice()=0; virtual bool isKnownSourceImage(const std::string &name)=0; + virtual video::ITexture* generateTextureFromMesh( + const TextureFromMeshParams ¶ms)=0; virtual void processQueue()=0; virtual void insertSourceImage(const std::string &name, video::IImage *img)=0; virtual void rebuildImagesAndTextures()=0; - virtual video::ITexture* generateTextureFromMesh( - const TextureFromMeshParams ¶ms)=0; }; IWritableTextureSource* createTextureSource(IrrlichtDevice *device); diff --git a/src/util/string.h b/src/util/string.h index d9390e33c..7531600e3 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -307,7 +307,7 @@ inline std::string unescape_string(std::string &s) { std::string res; - for (size_t i = 0; i <= s.length(); i++) { + for (size_t i = 0; i < s.length(); i++) { if (s[i] == '\\') i++; res += s[i]; -- cgit v1.2.3