|
|
@@ -22,6 +22,8 @@
|
|
|
|
|
|
|
|
|
#include "../Core/Context.h"
|
|
|
+#include "../IO/Log.h"
|
|
|
+
|
|
|
#include "ScriptComponentFile.h"
|
|
|
#include "ScriptComponent.h"
|
|
|
|
|
|
@@ -29,6 +31,7 @@ namespace Atomic
|
|
|
{
|
|
|
|
|
|
ScriptComponent::ScriptComponent(Context* context) : Component(context),
|
|
|
+ saving_(false),
|
|
|
loading_(false)
|
|
|
|
|
|
{
|
|
|
@@ -38,9 +41,7 @@ ScriptComponent::ScriptComponent(Context* context) : Component(context),
|
|
|
void ScriptComponent::RegisterObject(Context* context)
|
|
|
{
|
|
|
ATOMIC_ACCESSOR_ATTRIBUTE("Is Enabled", IsEnabled, SetEnabled, bool, true, AM_DEFAULT);
|
|
|
-
|
|
|
ATOMIC_ACCESSOR_ATTRIBUTE("FieldValues", GetFieldValuesAttr, SetFieldValuesAttr, VariantMap, Variant::emptyVariantMap, AM_FILE);
|
|
|
-
|
|
|
}
|
|
|
|
|
|
ScriptComponent::~ScriptComponent()
|
|
|
@@ -66,14 +67,185 @@ bool ScriptComponent::LoadXML(const XMLElement& source, bool setInstanceDefault)
|
|
|
return success;
|
|
|
}
|
|
|
|
|
|
+bool ScriptComponent::Save(Serializer& dest) const
|
|
|
+{
|
|
|
+ saving_ = true;
|
|
|
+ bool success = Component::Save(dest);
|
|
|
+ saving_ = false;
|
|
|
+
|
|
|
+ return success;
|
|
|
+}
|
|
|
+
|
|
|
+bool ScriptComponent::SaveXML(XMLElement& dest) const
|
|
|
+{
|
|
|
+ saving_ = true;
|
|
|
+ bool success = Component::SaveXML(dest);
|
|
|
+ saving_ = false;
|
|
|
+
|
|
|
+ return success;
|
|
|
+}
|
|
|
+
|
|
|
const VariantMap& ScriptComponent::GetFieldValuesAttr() const
|
|
|
{
|
|
|
+ ScriptComponentFile* componentFile = GetComponentFile();
|
|
|
+ const String& classname = GetComponentClassName();
|
|
|
+
|
|
|
+ if (saving_ && componentFile && classname.Length())
|
|
|
+ {
|
|
|
+ // When serializing enumerations, enum integer values are converted to enum strings
|
|
|
+ // This makes them independent of enum values/order changing
|
|
|
+
|
|
|
+ fieldValuesAttr_ = fieldValues_;
|
|
|
+
|
|
|
+ const EnumMap& enums = componentFile->GetEnums(classname);
|
|
|
+ VariantMap::ConstIterator itr = fieldValues_.Begin();
|
|
|
+ String fieldName;
|
|
|
+
|
|
|
+ while (itr != fieldValues_.End())
|
|
|
+ {
|
|
|
+ const StringHash& nameHash = itr->first_;
|
|
|
+ const Variant& v = itr->second_;
|
|
|
+ const FieldInfo* fieldInfo = 0;
|
|
|
+
|
|
|
+ bool skip = false;
|
|
|
+
|
|
|
+ // If we're not a numeric field, can skip
|
|
|
+ if (v.GetType() != VAR_INT &&
|
|
|
+ v.GetType() != VAR_FLOAT &&
|
|
|
+ v.GetType() != VAR_DOUBLE)
|
|
|
+ {
|
|
|
+ skip = true;
|
|
|
+ }
|
|
|
+ else if (!StringHash::GetSignificantString(nameHash, fieldName))
|
|
|
+ {
|
|
|
+ ATOMIC_LOGWARNING("ScriptComponent::GetFieldValuesAttr - unable to retrieve field name");
|
|
|
+ skip = true;
|
|
|
+ }
|
|
|
+ else if (!(fieldInfo = componentFile->GetFields(classname)[fieldName]) || !fieldInfo->isEnum_)
|
|
|
+ {
|
|
|
+ skip = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (skip)
|
|
|
+ {
|
|
|
+ itr++;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ int intValue = v.GetInt();
|
|
|
+
|
|
|
+ EnumMap::ConstIterator eitr = enums.Begin();
|
|
|
+
|
|
|
+ // find corresponding enum, and convert to enum name representation
|
|
|
+ while (eitr != enums.End())
|
|
|
+ {
|
|
|
+ if (!eitr->first_.Compare(fieldName, false))
|
|
|
+ {
|
|
|
+ const Vector<EnumInfo>& infos = eitr->second_;
|
|
|
+
|
|
|
+ for (unsigned i = 0; i < infos.Size(); i++)
|
|
|
+ {
|
|
|
+ if (intValue == infos[i].value_)
|
|
|
+ {
|
|
|
+ // use enum name string instead of numeric value
|
|
|
+ fieldValuesAttr_[nameHash] = infos[i].name_;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ eitr++;
|
|
|
+ }
|
|
|
+
|
|
|
+ itr++;
|
|
|
+ }
|
|
|
+
|
|
|
+ return fieldValuesAttr_;
|
|
|
+ }
|
|
|
+
|
|
|
return fieldValues_;
|
|
|
}
|
|
|
|
|
|
void ScriptComponent::SetFieldValuesAttr(const VariantMap& value)
|
|
|
{
|
|
|
fieldValues_ = value;
|
|
|
+
|
|
|
+ ScriptComponentFile* componentFile = GetComponentFile();
|
|
|
+ const String& classname = GetComponentClassName();
|
|
|
+
|
|
|
+ if (loading_ && componentFile && classname.Length())
|
|
|
+ {
|
|
|
+ // When serializing enumerations, enum integer values are converted to enum strings
|
|
|
+ // This makes them independent of enum values/order changing
|
|
|
+
|
|
|
+ const EnumMap& enums = componentFile->GetEnums(classname);
|
|
|
+ VariantMap::ConstIterator itr = value.Begin();
|
|
|
+ String fieldName;
|
|
|
+
|
|
|
+ // run through field values looking for enum name strings
|
|
|
+ // which need to be converted from string to numeric representation
|
|
|
+ while (itr != value.End())
|
|
|
+ {
|
|
|
+ const StringHash& nameHash = itr->first_;
|
|
|
+ const FieldInfo* fieldInfo = 0;
|
|
|
+
|
|
|
+ bool skip = false;
|
|
|
+
|
|
|
+ if (itr->second_.GetType() != VAR_STRING)
|
|
|
+ {
|
|
|
+ skip = true;
|
|
|
+ }
|
|
|
+ else if (!StringHash::GetSignificantString(nameHash, fieldName))
|
|
|
+ {
|
|
|
+ ATOMIC_LOGWARNING("ScriptComponent::SetFieldValuesAttr - unable to retrieve field name");
|
|
|
+ skip = true;
|
|
|
+ }
|
|
|
+ else if (!(fieldInfo = componentFile->GetFields(classname)[fieldName]) || !fieldInfo->isEnum_)
|
|
|
+ {
|
|
|
+ skip = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (skip)
|
|
|
+ {
|
|
|
+ itr++;
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ EnumMap::ConstIterator eitr = enums.Begin();
|
|
|
+ const String& svalue = itr->second_.GetString();
|
|
|
+
|
|
|
+ // find the corresponding enum if any
|
|
|
+ while (eitr != enums.End())
|
|
|
+ {
|
|
|
+ if (!eitr->first_.Compare(fieldName, false))
|
|
|
+ {
|
|
|
+ const Vector<EnumInfo>& infos = eitr->second_;
|
|
|
+
|
|
|
+ // default
|
|
|
+ fieldValues_[nameHash] = infos.Size() > 0 ? infos[0].value_ : 0;
|
|
|
+
|
|
|
+ for (unsigned i = 0; i < infos.Size(); i++)
|
|
|
+ {
|
|
|
+ if (!svalue.Compare(infos[i].name_, false))
|
|
|
+ {
|
|
|
+ fieldValues_[nameHash] = infos[i].value_;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ eitr++;
|
|
|
+ }
|
|
|
+
|
|
|
+ itr++;
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
}
|
|
|
|
|
|
}
|