1 /* 2 Copyright (C) 2010-2014 Kristian Duske 3 4 This file is part of TrenchBroom. 5 6 TrenchBroom is free software: you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 11 TrenchBroom is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with TrenchBroom. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #include "EntityAttributes.h" 21 22 #include "Exceptions.h" 23 #include "Assets/EntityDefinition.h" 24 25 namespace TrenchBroom { 26 namespace Model { 27 const String AttributeEscapeChars = "\"\n\\"; 28 29 namespace AttributeNames { 30 const AttributeName Classname = "classname"; 31 const AttributeName Origin = "origin"; 32 const AttributeName Wad = "wad"; 33 const AttributeName Textures = "_tb_textures"; 34 const AttributeName Mods = "_tb_mod"; 35 const AttributeName Spawnflags = "spawnflags"; 36 const AttributeName EntityDefinitions = "_tb_def"; 37 const AttributeName Angle = "angle"; 38 const AttributeName Angles = "angles"; 39 const AttributeName Mangle = "mangle"; 40 const AttributeName Target = "target"; 41 const AttributeName Targetname = "targetname"; 42 const AttributeName Killtarget = "killtarget"; 43 const AttributeName GroupType = "_tb_type"; 44 const AttributeName LayerId = "_tb_id"; 45 const AttributeName LayerName = "_tb_name"; 46 const AttributeName Layer = "_tb_layer"; 47 const AttributeName GroupId = "_tb_id"; 48 const AttributeName GroupName = "_tb_name"; 49 const AttributeName Group = "_tb_group"; 50 const AttributeName Message = "_tb_message"; 51 } 52 53 namespace AttributeValues { 54 const AttributeValue WorldspawnClassname = "worldspawn"; 55 const AttributeValue NoClassname = "undefined"; 56 const AttributeValue LayerClassname = "func_group"; 57 const AttributeValue GroupClassname = "func_group"; 58 const AttributeValue GroupTypeLayer = "_tb_layer"; 59 const AttributeValue GroupTypeGroup = "_tb_group"; 60 } 61 numberedAttributePrefix(const String & name)62 String numberedAttributePrefix(const String& name) { 63 size_t i = 0; 64 while (i < name.size() && name[i] < '0' && name[i] > '9') 65 ++i; 66 if (i == name.size()) 67 return ""; 68 for (size_t j = i; j < name.size(); ++j) { 69 if (name[j] < '0' || name[j] > '9') 70 return ""; 71 } 72 return name.substr(0, i); 73 } 74 isNumberedAttribute(const String & prefix,const AttributeName & name)75 bool isNumberedAttribute(const String& prefix, const AttributeName& name) { 76 if (name.size() < prefix.size()) 77 return false; 78 for (size_t i = 0; i < prefix.size(); ++i) 79 if (name[i] != prefix[i]) 80 return false; 81 for (size_t i = prefix.size(); i < name.size(); ++i) 82 if (name[i] < '0' || name[i] > '9') 83 return false; 84 return true; 85 } 86 87 const EntityAttribute::List EntityAttribute::EmptyList(0); 88 EntityAttribute()89 EntityAttribute::EntityAttribute() : 90 m_definition(NULL) {} 91 EntityAttribute(const AttributeName & name,const AttributeValue & value,const Assets::AttributeDefinition * definition)92 EntityAttribute::EntityAttribute(const AttributeName& name, const AttributeValue& value, const Assets::AttributeDefinition* definition) : 93 m_name(name), 94 m_value(value), 95 m_definition(definition) {} 96 operator <(const EntityAttribute & rhs) const97 bool EntityAttribute::operator<(const EntityAttribute& rhs) const { 98 return compare(rhs) < 0; 99 } 100 compare(const EntityAttribute & rhs) const101 int EntityAttribute::compare(const EntityAttribute& rhs) const { 102 const int nameCmp = m_name.compare(rhs.m_name); 103 if (nameCmp != 0) 104 return nameCmp; 105 return m_value.compare(rhs.m_value); 106 } 107 name() const108 const AttributeName& EntityAttribute::name() const { 109 return m_name; 110 } 111 value() const112 const AttributeValue& EntityAttribute::value() const { 113 return m_value; 114 } 115 definition() const116 const Assets::AttributeDefinition* EntityAttribute::definition() const { 117 return m_definition; 118 } 119 setName(const AttributeName & name,const Assets::AttributeDefinition * definition)120 void EntityAttribute::setName(const AttributeName& name, const Assets::AttributeDefinition* definition) { 121 m_name = name; 122 m_definition = definition; 123 } 124 setValue(const AttributeValue & value)125 void EntityAttribute::setValue(const AttributeValue& value) { 126 m_value = value; 127 } 128 isLayer(const String & classname,const EntityAttribute::List & attributes)129 bool isLayer(const String& classname, const EntityAttribute::List& attributes) { 130 if (classname != Model::AttributeValues::LayerClassname) 131 return false; 132 const AttributeValue& groupType = findAttribute(attributes, Model::AttributeNames::GroupType); 133 return groupType == Model::AttributeValues::GroupTypeLayer; 134 } 135 isGroup(const String & classname,const EntityAttribute::List & attributes)136 bool isGroup(const String& classname, const EntityAttribute::List& attributes) { 137 if (classname != Model::AttributeValues::GroupClassname) 138 return false; 139 const AttributeValue& groupType = findAttribute(attributes, Model::AttributeNames::GroupType); 140 return groupType == Model::AttributeValues::GroupTypeGroup; 141 } 142 isWorldspawn(const String & classname,const EntityAttribute::List & attributes)143 bool isWorldspawn(const String& classname, const EntityAttribute::List& attributes) { 144 return classname == Model::AttributeValues::WorldspawnClassname; 145 } 146 findAttribute(const EntityAttribute::List & attributes,const AttributeName & name,const AttributeValue & defaultValue)147 const AttributeValue& findAttribute(const EntityAttribute::List& attributes, const AttributeName& name, const AttributeValue& defaultValue) { 148 Model::EntityAttribute::List::const_iterator it, end; 149 for (it = attributes.begin(), end = attributes.end(); it != end; ++it) { 150 if (name == it->name()) 151 return it->value(); 152 } 153 return defaultValue; 154 } 155 attributes() const156 const EntityAttribute::List& EntityAttributes::attributes() const { 157 return m_attributes; 158 } 159 setAttributes(const EntityAttribute::List & attributes)160 void EntityAttributes::setAttributes(const EntityAttribute::List& attributes) { 161 m_attributes = attributes; 162 rebuildIndex(); 163 } 164 addOrUpdateAttribute(const AttributeName & name,const AttributeValue & value,const Assets::AttributeDefinition * definition)165 const EntityAttribute& EntityAttributes::addOrUpdateAttribute(const AttributeName& name, const AttributeValue& value, const Assets::AttributeDefinition* definition) { 166 EntityAttribute::List::iterator it = findAttribute(name); 167 if (it != m_attributes.end()) { 168 assert(it->definition() == definition); 169 it->setValue(value); 170 return *it; 171 } else { 172 m_attributes.push_back(EntityAttribute(name, value, definition)); 173 m_index.insert(name, --m_attributes.end()); 174 return m_attributes.back(); 175 } 176 } 177 renameAttribute(const AttributeName & name,const AttributeName & newName,const Assets::AttributeDefinition * newDefinition)178 void EntityAttributes::renameAttribute(const AttributeName& name, const AttributeName& newName, const Assets::AttributeDefinition* newDefinition) { 179 EntityAttribute::List::iterator it = findAttribute(name); 180 if (it == m_attributes.end()) 181 return; 182 m_index.remove(it->name(), it); 183 it->setName(newName, newDefinition); 184 m_index.insert(it->name(), it); 185 } 186 removeAttribute(const AttributeName & name)187 void EntityAttributes::removeAttribute(const AttributeName& name) { 188 EntityAttribute::List::iterator it = findAttribute(name); 189 if (it == m_attributes.end()) 190 return; 191 m_index.remove(name, it); 192 m_attributes.erase(it); 193 } 194 updateDefinitions(const Assets::EntityDefinition * entityDefinition)195 void EntityAttributes::updateDefinitions(const Assets::EntityDefinition* entityDefinition) { 196 EntityAttribute::List::iterator it, end; 197 for (it = m_attributes.begin(), end = m_attributes.end(); it != end; ++it) { 198 EntityAttribute& attribute = *it; 199 const AttributeName& name = attribute.name(); 200 const Assets::AttributeDefinition* attributeDefinition = Assets::EntityDefinition::safeGetAttributeDefinition(entityDefinition, name); 201 attribute.setName(name, attributeDefinition); 202 } 203 } 204 hasAttribute(const AttributeName & name) const205 bool EntityAttributes::hasAttribute(const AttributeName& name) const { 206 return findAttribute(name) != m_attributes.end(); 207 } 208 hasAttribute(const AttributeName & name,const AttributeValue & value) const209 bool EntityAttributes::hasAttribute(const AttributeName& name, const AttributeValue& value) const { 210 const EntityAttribute::List::const_iterator it = findAttribute(name); 211 if (it == m_attributes.end()) 212 return false; 213 return it->value() == value; 214 } 215 hasAttributeWithPrefix(const AttributeName & prefix,const AttributeValue & value) const216 bool EntityAttributes::hasAttributeWithPrefix(const AttributeName& prefix, const AttributeValue& value) const { 217 return containsValue(m_index.queryPrefixMatches(prefix), value); 218 } 219 hasNumberedAttribute(const AttributeName & prefix,const AttributeValue & value) const220 bool EntityAttributes::hasNumberedAttribute(const AttributeName& prefix, const AttributeValue& value) const { 221 return containsValue(m_index.queryNumberedMatches(prefix), value); 222 } 223 snapshot(const AttributeName & name) const224 EntityAttributeSnapshot EntityAttributes::snapshot(const AttributeName& name) const { 225 const AttributeIndex::QueryResult matches = m_index.queryExactMatches(name); 226 if (matches.empty()) 227 return EntityAttributeSnapshot(name); 228 229 assert(matches.size() == 1); 230 return EntityAttributeSnapshot(name, matches.front()->value()); 231 } 232 containsValue(const AttributeIndex::QueryResult & matches,const AttributeValue & value) const233 bool EntityAttributes::containsValue(const AttributeIndex::QueryResult& matches, const AttributeValue& value) const { 234 if (matches.empty()) 235 return false; 236 237 AttributeIndex::QueryResult::const_iterator it, end; 238 for (it = matches.begin(), end = matches.end(); it != end; ++it) { 239 const EntityAttribute::List::iterator attrIt = *it; 240 const EntityAttribute& attribute = *attrIt; 241 if (attribute.value() == value) 242 return true; 243 } 244 245 return false; 246 } 247 attribute(const AttributeName & name) const248 const AttributeValue* EntityAttributes::attribute(const AttributeName& name) const { 249 EntityAttribute::List::const_iterator it = findAttribute(name); 250 if (it == m_attributes.end()) 251 return NULL; 252 return &it->value(); 253 } 254 safeAttribute(const AttributeName & name,const AttributeValue & defaultValue) const255 const AttributeValue& EntityAttributes::safeAttribute(const AttributeName& name, const AttributeValue& defaultValue) const { 256 const AttributeValue* value = attribute(name); 257 if (value == NULL) 258 return defaultValue; 259 return *value; 260 } 261 numberedAttributes(const String & prefix) const262 EntityAttribute::List EntityAttributes::numberedAttributes(const String& prefix) const { 263 EntityAttribute::List result; 264 265 EntityAttribute::List::const_iterator it, end; 266 for (it = m_attributes.begin(), end = m_attributes.end(); it != end; ++it) { 267 const EntityAttribute& attribute = *it; 268 if (isNumberedAttribute(prefix, attribute.name())) 269 result.push_back(attribute); 270 } 271 272 return result; 273 } 274 findAttribute(const AttributeName & name) const275 EntityAttribute::List::const_iterator EntityAttributes::findAttribute(const AttributeName& name) const { 276 const AttributeIndex::QueryResult matches = m_index.queryExactMatches(name); 277 if (matches.empty()) 278 return m_attributes.end(); 279 280 assert(matches.size() == 1); 281 return matches.front(); 282 } 283 findAttribute(const AttributeName & name)284 EntityAttribute::List::iterator EntityAttributes::findAttribute(const AttributeName& name) { 285 const AttributeIndex::QueryResult matches = m_index.queryExactMatches(name); 286 if (matches.empty()) 287 return m_attributes.end(); 288 289 assert(matches.size() == 1); 290 return matches.front(); 291 } 292 rebuildIndex()293 void EntityAttributes::rebuildIndex() { 294 m_index.clear(); 295 296 EntityAttribute::List::iterator it, end; 297 for (it = m_attributes.begin(), end = m_attributes.end(); it != end; ++it) { 298 const EntityAttribute& attribute = *it; 299 m_index.insert(attribute.name(), it); 300 } 301 } 302 } 303 } 304