Gracefully deal with entity attributes of the same name. This is needed for

the Input/Output system. We append numerations separated by a '#' character
and strip the when saving the map. The editor will intelligently pick a
name for us.
This commit is contained in:
Marco Cawthorne 2021-06-06 12:27:36 +02:00
parent adc1c4ea15
commit 826d115cb1
2 changed files with 75 additions and 5 deletions

View file

@ -374,6 +374,7 @@ typedef MemberCaller<KeyValue, void(const CopiedString&), &KeyValue::importState
/// - Notifies observers when a pair is inserted or removed. /// - Notifies observers when a pair is inserted or removed.
/// - Provides undo support through the global undo system. /// - Provides undo support through the global undo system.
/// - New keys are appended to the end of the list. /// - New keys are appended to the end of the list.
#include "stream/stringstream.h"
class EntityKeyValues : public Entity class EntityKeyValues : public Entity
{ {
public: public:
@ -441,15 +442,82 @@ private:
} }
} }
/* see if our key already exists in here */
void insert( const char* key, const char* value ){ void insert( const char* key, const char* value ){
int dupecheck = 0;
if (!strcmp(key, "classname"))
dupecheck = 1;
else if (!strcmp(key, "origin"))
dupecheck = 1;
else if (!strcmp(key, "model"))
dupecheck = 1;
else if (!strcmp(key, "angles"))
dupecheck = 1;
else if (!strcmp(key, "angle"))
dupecheck = 1;
else if (!strcmp(key, "alpha"))
dupecheck = 1;
else if (!strcmp(key, "rendermode"))
dupecheck = 1;
else if (!strcmp(key, "renderamt"))
dupecheck = 1;
else if (!strcmp(key, "rendercolor"))
dupecheck = 1;
else if (!strcmp(key, "velocity"))
dupecheck = 1;
else if (!strcmp(key, "solid"))
dupecheck = 1;
else if (!strcmp(key, "movetype"))
dupecheck = 1;
else if (!strcmp(key, "avelocity"))
dupecheck = 1;
else if (!strcmp(key, "skin"))
dupecheck = 1;
else if (!strcmp(key, "effects"))
dupecheck = 1;
else if (!strcmp(key, "target"))
dupecheck = 1;
else if (!strcmp(key, "targetname"))
dupecheck = 1;
else if (!strcmp(key, "killtarget"))
dupecheck = 1;
else if (!strcmp(key, "shadows"))
dupecheck = 1;
KeyValues::iterator i = m_keyValues.find( key ); KeyValues::iterator i = m_keyValues.find( key );
if ( i != m_keyValues.end() ) {
( *i ).second->assign( value ); /* does the key already exist */
if (i != m_keyValues.end() ) {
/* re-assign only when we're a special field, else pick a new name */
if (dupecheck) {
( *i ).second->assign( value );
printf("[ENTLIB]: dupe found, setting %s to %s\n", key, value);
} else {
bool b = true;
unsigned int num = 0;
StringOutputStream new_key(64);
/* loop through and generate an enumerated variant */
do {
/* keep incrementing num until we find a free slot */
num++;
new_key.clear();
new_key << key << "#" << Unsigned(num);
i = m_keyValues.find(new_key.c_str());
if (i == m_keyValues.end()) {
insert(new_key.c_str(), value);
b = false;
}
} while (b != false);
}
} }
else else
{ {
m_undo.save(); m_undo.save();
insert( key, KeyValuePtr( new KeyValue( value, EntityClass_valueForKey( *m_eclass, key ) ) ) ); insert( key, KeyValuePtr( new KeyValue( value, EntityClass_valueForKey( *m_eclass, key ) ) ) );
printf("[ENTLIB]: inserting key %s = %s\n", key, value);
} }
} }

View file

@ -49,9 +49,11 @@ void Entity_ExportTokens(const Entity &entity, TokenWriter &writer)
void visit(const char *key, const char *value) void visit(const char *key, const char *value)
{ {
m_writer.writeString(key); /* cut anything after # including the symbol itself */
m_writer.writeString(value); StringTokeniser st(key, "#");
m_writer.nextLine(); m_writer.writeString(st.getToken());
m_writer.writeString(value);
m_writer.nextLine();
} }
} visitor(writer); } visitor(writer);