diff --git a/src/items/item.cpp b/src/items/item.cpp index ef4a44938..e6032cca5 100644 --- a/src/items/item.cpp +++ b/src/items/item.cpp @@ -31,24 +31,14 @@ #include "utils/vec3.hpp" Item::Item(ItemType type, const Vec3& xyz, const Vec3& normal, - scene::IMesh* mesh, scene::IMesh* lowres_mesh, unsigned int item_id) + scene::IMesh* mesh, scene::IMesh* lowres_mesh) { assert(type != ITEM_TRIGGER); // use other constructor for that - setType(type); - m_event_handler = NULL; - m_xyz = xyz; - m_deactive_time = 0; + initItem(type, xyz); m_distance_2 = 0.8f; // Sets heading to 0, and sets pitch and roll depending on the normal. */ m_original_hpr = Vec3(0, normal); - m_item_id = item_id; - m_original_type = ITEM_NONE; - m_collected = false; - m_time_till_return = 0.0f; // not strictly necessary, see isCollected() - m_disappear_counter = m_type==ITEM_BUBBLEGUM - ? stk_config->m_bubble_gum_counter - : -1 ; m_original_mesh = mesh; m_original_lowmesh = lowres_mesh; m_listener = NULL; @@ -83,7 +73,7 @@ Item::Item(ItemType type, const Vec3& xyz, const Vec3& normal, m_node->setPosition(xyz.toIrrVector()); m_node->setRotation(m_original_hpr.toIrrHPR()); m_node->grab(); -} // Item +} // Item(type, xyz, normal, mesh, lowres_mesh) //----------------------------------------------------------------------------- @@ -91,37 +81,46 @@ Item::Item(ItemType type, const Vec3& xyz, const Vec3& normal, * Trigger items are invisible and can be used to trigger a behavior when * approaching a point. */ -Item::Item (const Vec3& xyz, float distance, TriggerItemListener* trigger, - unsigned int item_id) +Item::Item(const Vec3& xyz, float distance, TriggerItemListener* trigger) { - m_type = ITEM_TRIGGER; - m_event_handler = NULL; - m_xyz = xyz; - m_deactive_time = 0; + initItem(ITEM_TRIGGER, xyz); // Sets heading to 0, and sets pitch and roll depending on the normal. */ m_original_hpr = Vec3(0, 0, 0); - m_item_id = item_id; - m_original_type = ITEM_NONE; - m_collected = false; - m_time_till_return = 0.0f; // not strictly necessary, see isCollected() - m_disappear_counter = -1; m_original_mesh = NULL; m_original_lowmesh = NULL; m_node = NULL; m_listener = trigger; - m_rotate = false; m_distance_2 = distance*distance; -} +} // Item(xyz, distance, trigger) //----------------------------------------------------------------------------- -/** Sets the type of this item, but also derived values, e.g. m_rotate. - * (bubblegums do not return). - * \param type New type of the item. +/** Initialises the item. + * \param type Type of the item. + */ +void Item::initItem(ItemType type, const Vec3 &xyz) +{ + m_type = type; + m_xyz = xyz; + m_event_handler = NULL; + m_item_id = -1; + m_collected = false; + m_original_type = ITEM_NONE; + m_deactive_time = 0; + m_time_till_return = 0.0f; // not strictly necessary, see isCollected() + m_rotate = (type!=ITEM_BUBBLEGUM) && (type!=ITEM_TRIGGER); + m_disappear_counter = m_type==ITEM_BUBBLEGUM + ? stk_config->m_bubble_gum_counter + : -1 ; +} // initItem + +//----------------------------------------------------------------------------- +/** Sets the type of the item (and also derived attributes lile m_rotate + * \param type Type of the item. */ void Item::setType(ItemType type) { m_type = type; - m_rotate = type!=ITEM_BUBBLEGUM; + m_rotate = (type!=ITEM_BUBBLEGUM) && (type!=ITEM_TRIGGER); } // setType //----------------------------------------------------------------------------- diff --git a/src/items/item.hpp b/src/items/item.hpp index a7aafb927..948cfaac2 100644 --- a/src/items/item.hpp +++ b/src/items/item.hpp @@ -130,8 +130,6 @@ private: * indicates that the item still exists, =0 that the item can be * deleted, and <0 that the item will never be deleted. */ int m_disappear_counter; - - void setType(ItemType type); /** callback used if type == ITEM_TRIGGER */ TriggerItemListener* m_listener; @@ -139,11 +137,14 @@ private: /** square distance at which item is collected */ float m_distance_2; + void initItem(ItemType type, const Vec3 &xyz); + void setType(ItemType type); + public: - Item (ItemType type, const Vec3& xyz, const Vec3& normal, - scene::IMesh* mesh, scene::IMesh* lowres_mesh, unsigned int item_id); - Item (const Vec3& xyz, float distance, TriggerItemListener* trigger, - unsigned int item_id); + Item(ItemType type, const Vec3& xyz, const Vec3& normal, + scene::IMesh* mesh, scene::IMesh* lowres_mesh); + Item(const Vec3& xyz, float distance, + TriggerItemListener* trigger); virtual ~Item (); void update (float delta); virtual void collected(const AbstractKart *kart, float t=2.0f); @@ -166,6 +167,9 @@ public: (xyz-m_xyz).length2()::const_iterator CI_type; ItemManager::ItemManager() { m_switch_time = -1.0f; - m_all_meshes.clear(); // The actual loading is done in loadDefaultItems // Prepare the switch to array, which stores which item should be @@ -68,6 +68,8 @@ void ItemManager::setSwitchItems(const std::vector &switch_items) } // setSwitchItems //----------------------------------------------------------------------------- +/** Clean up all textures. This is necessary when switching resolution etc. + */ void ItemManager::removeTextures() { for(AllItemTypes::iterator i =m_all_items.begin(); @@ -77,85 +79,100 @@ void ItemManager::removeTextures() } m_all_items.clear(); - for(CI_type i=m_all_meshes.begin(); i!=m_all_meshes.end(); ++i) + for(unsigned int i=0; isecond->drop(); + if(m_item_mesh[i] ) m_item_mesh[i]->drop(); + if(m_item_lowres_mesh[i]) m_item_lowres_mesh[i]->drop(); } - for(CI_type i=m_all_low_meshes.begin(); i!=m_all_low_meshes.end(); ++i) - { - i->second->drop(); - } - m_all_meshes.clear(); - m_all_low_meshes.clear(); } // removeTextures //----------------------------------------------------------------------------- +/** Destructor. Cleans up all items and meshes stored. + */ ItemManager::~ItemManager() -{ - for(CI_type i=m_all_meshes.begin(); i!=m_all_meshes.end(); ++i) +{ + for(unsigned int i=0; isecond->drop(); + if(m_item_mesh[i] ) m_item_mesh[i]->drop(); + if(m_item_lowres_mesh[i]) m_item_lowres_mesh[i]->drop(); } - m_all_meshes.clear(); - - for(CI_type i=m_all_low_meshes.begin(); i!=m_all_low_meshes.end(); ++i) - { - i->second->drop(); - } - m_all_low_meshes.clear(); } // ~ItemManager //----------------------------------------------------------------------------- +/** Loads the default item meshes (high- and low-resolution). + */ void ItemManager::loadDefaultItems() { - // The names must be given in the order of the definition of ItemType - // in item.hpp. Note that bubblegum strictly isn't an item, - // it is implemented as one, and so loaded here, too. - static const std::string item_names[] = {"bonus-box", "banana", - "nitro-big", "nitro-small", - "bubblegum", "trigger" }; + m_item_mesh.resize(Item::ITEM_LAST-Item::ITEM_FIRST+1, NULL); + m_item_lowres_mesh.resize(Item::ITEM_LAST-Item::ITEM_FIRST+1, NULL); + + // A temporary mapping of items to names used in the XML file: + std::map item_names; + item_names[Item::ITEM_BANANA ] = "banana"; + item_names[Item::ITEM_BONUS_BOX ] = "bonus-box"; + item_names[Item::ITEM_BUBBLEGUM ] = "bubblegum"; + item_names[Item::ITEM_NITRO_BIG ] = "nitro-big"; + item_names[Item::ITEM_NITRO_SMALL] = "nitro-small"; + item_names[Item::ITEM_TRIGGER ] = "trigger"; + const std::string file_name = file_manager->getDataFile("items.xml"); const XMLNode *root = file_manager->createXMLTree(file_name); for(unsigned int i=Item::ITEM_FIRST; i<=Item::ITEM_LAST; i++) { - const XMLNode *node = root->getNode(item_names[i]); - std::string model_filename, lowres_model_filename; - if (node) - { - node->get("model", &model_filename); - node->get("lowmodel", &lowres_model_filename); - } - else - { - continue; - } - - scene::IMesh *mesh = irr_driver->getAnimatedMesh(model_filename); - scene::IMesh *lowres_mesh = NULL; - - if (lowres_model_filename.size() > 0) - lowres_mesh = irr_driver->getMesh(lowres_model_filename); - + const std::string &name = item_names[(Item::ItemType)i]; + const XMLNode *node = root->getNode(name); + if (!node) continue; + + std::string model_filename; + node->get("model", &model_filename); + + scene::IMesh *mesh = irr_driver->getAnimatedMesh(model_filename); if(!node || model_filename.size()==0 || !mesh) { - fprintf(stderr, "Item model '%s' in items.xml could not be loaded - aborting", - item_names[i].c_str()); + fprintf(stderr, "Item model '%s' in items.xml could not be loaded " + "- aborting", name.c_str()); exit(-1); } - std::string shortName = - StringUtils::getBasename(StringUtils::removeExtension(model_filename)); - m_all_meshes[shortName] = mesh; - m_item_mesh[i] = mesh; - m_item_lowres_mesh[i] = lowres_mesh; - mesh->grab(); - - if (lowres_mesh != NULL) - m_all_low_meshes[shortName] = lowres_mesh; - if (lowres_mesh != NULL) lowres_mesh->grab(); + mesh->grab(); + m_item_mesh[i] = mesh; + + std::string lowres_model_filename; + node->get("lowmodel", &lowres_model_filename); + m_item_lowres_mesh[i] = lowres_model_filename.size() == 0 + ? NULL + : irr_driver->getMesh(lowres_model_filename); + + if (m_item_lowres_mesh[i]) m_item_lowres_mesh[i]->grab(); } // for i delete root; } // loadDefaultItems +//----------------------------------------------------------------------------- +/** Inserts the new item into the items management data structures, if possible + * reusing an existing, unused entry (e.g. due to a removed bubble gum). Then + * the item is also added to the quad-wise list of items. + */ +void ItemManager::insertItem(Item *item) +{ + // Find where the item can be stored in the index list: either in a + // previously deleted entry, otherwise at the end. + int index = -1; + for(index=m_all_items.size()-1; index>=0 && m_all_items[index]; index--) {} + + if(index==-1) index = m_all_items.size(); + + if(index<(int)m_all_items.size()) + m_all_items[index] = item; + else + m_all_items.push_back(item); + item->setItemId(index); + + // Now insert into the appropriate quad list + const Vec3 &xyz = item->getXYZ(); + int sector = QuadGraph::UNKNOWN_SECTOR; + QuadGraph::get()->findRoadSector(xyz, §or); +} // insertItem + //----------------------------------------------------------------------------- /** Creates a new item. * \param type Type of the item. @@ -167,15 +184,10 @@ void ItemManager::loadDefaultItems() Item* ItemManager::newItem(Item::ItemType type, const Vec3& xyz, const Vec3 &normal, AbstractKart *parent) { - // Find where the item can be stored in the index list: either in a - // previously deleted entry, otherwise at the end. - int index = -1; - for(index=m_all_items.size()-1; index>=0 && m_all_items[index]; index--) {} + Item* item = new Item(type, xyz, normal, m_item_mesh[type], + m_item_lowres_mesh[type]); - if(index==-1) index = m_all_items.size(); - Item* item; - item = new Item(type, xyz, normal, m_item_mesh[type], - m_item_lowres_mesh[type], index); + insertItem(item); if(parent != NULL) item->setParent(parent); if(m_switch_time>=0) { @@ -183,11 +195,6 @@ Item* ItemManager::newItem(Item::ItemType type, const Vec3& xyz, item->switchTo(new_type, m_item_mesh[(int)new_type], m_item_lowres_mesh[(int)new_type]); } - if(index<(int)m_all_items.size()) - m_all_items[index] = item; - else - m_all_items.push_back(item); - return item; } // newItem @@ -198,20 +205,10 @@ Item* ItemManager::newItem(Item::ItemType type, const Vec3& xyz, Item* ItemManager::newItem(const Vec3& xyz, float distance, TriggerItemListener* listener) { - // Find where the item can be stored in the index list: either in a - // previously deleted entry, otherwise at the end. - int index = -1; - for(index=m_all_items.size()-1; index>=0 && m_all_items[index]; index--) {} - - if(index==-1) index = m_all_items.size(); Item* item; - item = new Item(xyz, distance, listener, index); + item = new Item(xyz, distance, listener); + insertItem(item); - if(index<(int)m_all_items.size()) - m_all_items[index] = item; - else - m_all_items.push_back(item); - return item; } // newItem diff --git a/src/items/item_manager.hpp b/src/items/item_manager.hpp index ee6c5bbe0..31693fd47 100644 --- a/src/items/item_manager.hpp +++ b/src/items/item_manager.hpp @@ -41,22 +41,23 @@ private: AllItemTypes m_all_items; /** This stores all item models. */ - scene::IMesh *m_item_mesh[Item::ITEM_LAST-Item::ITEM_FIRST+1]; - scene::IMesh *m_item_lowres_mesh[Item::ITEM_LAST-Item::ITEM_FIRST+1]; - - /** Stores all meshes for all items. */ - std::map m_all_meshes; - std::map m_all_low_meshes; + std::vector m_item_mesh; + std::vector m_item_lowres_mesh; + + /** The filename of item.xml, which can be overwritten from the command line + * in order to select different models. */ std::string m_user_filename; - /** What item is item is switched to. */ + /** What item this item is switched to. */ std::vector m_switch_to; /** Remaining time that items should remain switched. If the * value is <0, it indicates that the items are not switched atm. */ float m_switch_time; + void ItemManager::insertItem(Item *item); + public: ItemManager(); ~ItemManager();