/** Copies this KartProperties to another one. Important: if you add any * pointers to kart_properties, the data structure they are pointing to * need to be copied here explicitely! * The AIProperties won't get cloned here as they don't differ for each player. * To clone this object for another kart use the copyFrom method. * \param source The source kart properties from which to copy this objects' * values. */ void KartProperties::copyForPlayer(const KartProperties *source) { *this = *source; // After the memcpy any pointers will be shared. // So all pointer variables need to be separately allocated and assigned. if (source->m_characteristic) { // Remove the shared reference by creating a new pointer m_characteristic.reset(new XmlCharacteristic()); m_characteristic->copyFrom(source->getCharacteristic()); // Combine the characteristics for this object. We can't copy it because // this object has other pointers (to m_characteristic). combineCharacteristics(); } } // copyForPlayer
/** Loads the kart properties from a file. * \param filename Filename to load. * \param node Name of the xml node to load the data from */ void KartProperties::load(const std::string &filename, const std::string &node) { // Get the default values from STKConfig. This will also allocate any // pointers used in KartProperties const XMLNode* root = new XMLNode(filename); std::string kart_type; if (root->get("type", &kart_type)) { // Handle the case that kart_type might be incorrect try { copyFrom(&stk_config->getKartProperties(kart_type)); } catch (std::out_of_range &) { copyFrom(&stk_config->getDefaultKartProperties()); } // try .. catch } else copyFrom(&stk_config->getDefaultKartProperties()); // m_kart_model must be initialised after assigning the default // values from stk_config (otherwise all kart_properties will // share the same KartModel m_kart_model = std::make_shared<KartModel>(/*is_master*/true); m_root = StringUtils::getPath(filename)+"/"; m_ident = StringUtils::getBasename(StringUtils::getPath(filename)); // If this is an addon kart, add "addon_" to the identifier - just in // case that an addon kart has the same directory name (and therefore // identifier) as an included kart. if(Addon::isAddon(filename)) { m_ident = Addon::createAddonId(m_ident); m_is_addon = true; } try { if(!root || root->getName()!="kart") { std::ostringstream msg; msg << "Couldn't load kart properties '" << filename << "': no kart node."; throw std::runtime_error(msg.str()); } getAllData(root); m_characteristic = std::make_shared<XmlCharacteristic>(root); combineCharacteristics(PLAYER_DIFFICULTY_NORMAL); } catch(std::exception& err) { Log::error("[KartProperties]", "Error while parsing KartProperties '%s':", filename.c_str()); Log::error("[KartProperties]", "%s", err.what()); } if(root) delete root; // Set a default group (that has to happen after init_default and load) if(m_groups.size()==0) m_groups.push_back(DEFAULT_GROUP_NAME); // Load material std::string materials_file = m_root+"materials.xml"; std::string unique_id = StringUtils::insertValues("karts/%s", m_ident.c_str()); file_manager->pushModelSearchPath(m_root); file_manager->pushTextureSearchPath(m_root, unique_id); #ifndef SERVER_ONLY if (CVS->isGLSL()) { SP::SPShaderManager::get()->loadSPShaders(m_root); } #endif STKTexManager::getInstance() ->setTextureErrorMessage("Error while loading kart '%s':", m_name); // addShared makes sure that these textures/material infos stay in memory material_manager->addSharedMaterial(materials_file); m_icon_file = m_root+m_icon_file; // Make permanent is important, since otherwise icons can get deleted // (e.g. when freeing temp. materials from a track, the last icon // would get deleted, too. m_icon_material = material_manager->getMaterial(m_icon_file, /*is_full_path*/true, /*make_permanent*/true, /*complain_if_not_found*/true, /*strip_path*/false); if (m_minimap_icon_file!="") { m_minimap_icon = STKTexManager::getInstance() ->getTexture(m_root+m_minimap_icon_file); } else m_minimap_icon = NULL; // Only load the model if the .kart file has the appropriate version, // otherwise warnings are printed. if (m_version >= 1) { const bool success = m_kart_model->loadModels(*this); if (!success) { file_manager->popTextureSearchPath(); file_manager->popModelSearchPath(); throw std::runtime_error("Cannot load kart models"); } } if(m_gravity_center_shift.getX()==UNDEFINED) { m_gravity_center_shift.setX(0); // Default: center at the very bottom of the kart. // If the kart is 'too high', its height will be changed in // kart.cpp, the same adjustment needs to be made here. if (m_kart_model->getHeight() > m_kart_model->getLength()*0.6f) m_gravity_center_shift.setY(m_kart_model->getLength()*0.6f*0.5f); else m_gravity_center_shift.setY(m_kart_model->getHeight()*0.5f); m_gravity_center_shift.setZ(0); } // The longer the kart,the bigger its turn radius if using an identical // wheel base, exactly proportionally to its length. // The wheel base is used to compensate this // We divide by 1.425 to have a default turn radius which conforms // closely (+-0,1%) with the specifications in kart_characteristics.xml m_wheel_base = fabsf(m_kart_model->getLength()/1.425f); m_shadow_material = material_manager->getMaterialSPM(m_shadow_file, "", "alphablend"); STKTexManager::getInstance()->unsetTextureErrorMessage(); file_manager->popTextureSearchPath(); file_manager->popModelSearchPath(); } // load
/** Loads the kart properties from a file. * \param filename Filename to load. * \param node Name of the xml node to load the data from */ void KartProperties::load(const std::string &filename, const std::string &node) { // Get the default values from STKConfig. This will also allocate any // pointers used in KartProperties const XMLNode* root = new XMLNode(filename); std::string kart_type; if (root->get("type", &kart_type)) { // Handle the case that kart_type might be incorrect try { copyFrom(&stk_config->getKartProperties(kart_type)); } catch (std::out_of_range) { copyFrom(&stk_config->getDefaultKartProperties()); } // try .. catch } else copyFrom(&stk_config->getDefaultKartProperties()); // m_kart_model must be initialised after assigning the default // values from stk_config (otherwise all kart_properties will // share the same KartModel m_kart_model.reset(new KartModel(/*is_master*/true)); m_root = StringUtils::getPath(filename)+"/"; m_ident = StringUtils::getBasename(StringUtils::getPath(filename)); // If this is an addon kart, add "addon_" to the identifier - just in // case that an addon kart has the same directory name (and therefore // identifier) as an included kart. if(Addon::isAddon(filename)) m_ident = Addon::createAddonId(m_ident); try { if(!root || root->getName()!="kart") { std::ostringstream msg; msg << "Couldn't load kart properties '" << filename << "': no kart node."; throw std::runtime_error(msg.str()); } getAllData(root); m_characteristic.reset(new XmlCharacteristic(root)); combineCharacteristics(); } catch(std::exception& err) { Log::error("[KartProperties]", "Error while parsing KartProperties '%s':", filename.c_str()); Log::error("[KartProperties]", "%s", err.what()); } if(root) delete root; // Set a default group (that has to happen after init_default and load) if(m_groups.size()==0) m_groups.push_back(DEFAULT_GROUP_NAME); // Load material std::string materials_file = m_root+"materials.xml"; file_manager->pushModelSearchPath (m_root); file_manager->pushTextureSearchPath(m_root); irr_driver->setTextureErrorMessage("Error while loading kart '%s':", m_name); // addShared makes sure that these textures/material infos stay in memory material_manager->addSharedMaterial(materials_file); m_icon_file = m_root+m_icon_file; // Make permanent is important, since otherwise icons can get deleted // (e.g. when freeing temp. materials from a track, the last icon // would get deleted, too. m_icon_material = material_manager->getMaterial(m_icon_file, /*is_full_path*/true, /*make_permanent*/true, /*complain_if_not_found*/true, /*strip_path*/false); if(m_minimap_icon_file!="") m_minimap_icon = irr_driver->getTexture(m_root+m_minimap_icon_file); else m_minimap_icon = NULL; if (m_minimap_icon == NULL) { m_minimap_icon = getUnicolorTexture(m_color); } // Only load the model if the .kart file has the appropriate version, // otherwise warnings are printed. if (m_version >= 1) { const bool success = m_kart_model->loadModels(*this); if (!success) { file_manager->popTextureSearchPath(); file_manager->popModelSearchPath(); throw std::runtime_error("Cannot load kart models"); } } if(m_gravity_center_shift.getX()==UNDEFINED) { m_gravity_center_shift.setX(0); // Default: center at the very bottom of the kart. // If the kart is 'too high', its height will be changed in // kart.cpp, the same adjustment needs to be made here. if (m_kart_model->getHeight() > m_kart_model->getLength()*0.6f) m_gravity_center_shift.setY(m_kart_model->getLength()*0.6f*0.5f); else m_gravity_center_shift.setY(m_kart_model->getHeight()*0.5f); m_gravity_center_shift.setZ(0); } // In older STK versions the physical wheels where moved 'wheel_radius' // into the physical body (i.e. 'hypothetical' wheel shape would not // poke out of the physical shape). In order to make the karts a bit more // stable, the physical wheel position (i.e. location of raycast) were // moved to be on the corner of the shape. In order to retain the same // steering behaviour, the wheel base (which in turn determines the // turn angle at certain speeds) is shortened by 2*wheel_radius // Wheel radius was always 0.25, and is now not used anymore, but in order // to keep existing steering behaviour, the same formula is still // used. m_wheel_base = fabsf(m_kart_model->getLength() - 2*0.25f); m_shadow_texture = irr_driver->getTexture(m_shadow_file); irr_driver->unsetTextureErrorMessage(); file_manager->popTextureSearchPath(); file_manager->popModelSearchPath(); } // load