Непонятки с сериализацией/десериализацией
Потихоньку разбираюсь в движке, что-то понимаю, что-то нет... Для своей игрушки написал компонент автомобиля, который, помимо прочего, загружает конфигурацию машины (положение колёс, параметры подвески, и пр.) из XML-файла, и потом настраивает встроенный RaycastVehicle соответствующим образом. Сложность возникла на этапе, когда вместо безликих
<variant type="Vector3" value="0.0 0.0 0.0" />
захотелось видеть в XML что-то вроде этого:
<attribute name="Position" value="0.0 0.0 0.0" />
Изначально чтение параметров тех же колёс почти полностью скопировал из RaycastVehicle, где параметры каждого колеса читались в виде VariantVector'а, но, как я уже упомянул, мне захотелось, что бы каждый параметр колеса (позиция, поворот, диаметр, и т.д.) был подписан, и потому я "раскурил" RaycastVehicle подробно. Как я понял, список строк с названиями параметров там стоит именно для того, что бы в XML-файле каждому параметру присваивалось определённое имя, вот только это у меня почему-то не заработало, и даже сам RaycastVehicle сериализировался всё тем же безликим VariantVector'ом. Покопался в функции Serializable::SaveXML() — вроде должно подписывать имена параметров, а не подписывает... Собственно, вопрос: это я чего-то не понимаю, или в движке проблема?
Dozorniy
> Собственно, вопрос: это я чего-то не понимаю, или в движке проблема?
думаю что в движке)
давно на ухе ничего не писал. но вот как я раньше писал и читал в XMLFile, там есть поле name
AS:
+ Показать
− Скрыть
void WriteMaterialFile(String materialFileName, String cachePathToLightmap )
{
String outFileName = GetFullPathForLightmapMaterials(true) + "/" + materialFileName;
XMLFile outMat;
XMLElement rootElem = outMat.CreateRoot("material");
XMLElement techniqueElem = rootElem.CreateChild("technique");
XMLElement cullElem = rootElem.CreateChild("cull");
cullElem.SetAttribute("value", "ccw");
XMLElement shadowCullElem = rootElem.CreateChild("shadowcull");
shadowCullElem.SetAttribute("value", "ccw");
techniqueElem.SetAttribute("name", "Techniques/DiffUnlitLightMap.xml");
XMLElement textureElem = rootElem.CreateChild("texture");
textureElem.SetAttribute("unit", "diffuse");
textureElem.SetAttribute("name", "Textures/white.png");
XMLElement textureElem2 = rootElem.CreateChild("texture");
textureElem2.SetAttribute("unit", "emissive");
textureElem2.SetAttribute("name", cachePathToLightmap);
XMLElement uScaleElem = rootElem.CreateChild("parameter");
uScaleElem.SetAttribute("name", "UOffset");
uScaleElem.SetVector3("value", Vector3(1 , 0, 0));
XMLElement vScaleElem = rootElem.CreateChild("parameter");
vScaleElem.SetAttribute("name", "VOffset");
vScaleElem.SetVector3("value", Vector3(0, 1, 0));
XMLElement diffuseElem = rootElem.CreateChild("parameter");
diffuseElem.SetAttribute("name", "MatDiffColor");
diffuseElem.SetColor("value", Color(1,1,1,1));
File outFile(outFileName, FILE_WRITE);
outMat.Save(outFile);
outFile.Close();
}
− Скрыть
bool ImportBakedData()
{
ui.cursor.shape = CS_BUSY;
log.Info("ImportBakedData -> begin()");
XMLFile@ xmlfile = XMLFile();
File@ gdlFile = File(lightmapTempDir +"/"+ GeomDataFileName, FILE_READ);
xmlfile.Load(gdlFile);
gdlFile.Close();
XMLElement root = xmlfile.GetRoot("files");
if (root.isNull)
{
log.Info("ImportBakedData error while parsing XMLFile : " + lightmapTempDir +"/"+ GeomDataFileName);
return false;
}
XPathQuery availableOBJFilesXPathQuery("//objfile");
XPathResultSet resultSet = availableOBJFilesXPathQuery.Evaluate(root);
XMLElement resultElem = resultSet.firstResult;
Array<String> filesShortNames;
Array<Vector3> worldPositions;
Array<String> lmGroups;
while(resultElem.notNull)
{
String objName = resultElem.GetAttribute("name");
uint nodeid = resultElem.GetInt("nodeid");
String lm = resultElem.GetAttribute("lm");
Vector3 position = resultElem.GetVector3("position");
String model = resultElem.GetAttribute("model");
Vector3 euler = resultElem.GetVector3("euler");
Quaternion quat = resultElem.GetQuaternion("quat");
String name = objName.Substring(0, objName.FindLast("."));
filesShortNames.Push(name);
worldPositions.Push(position);
lmGroups.Push(lm);
resultElem = resultElem.nextResult;
}
for (int i=0; i<lmGroups.length; ++i)
{
WriteMaterialFile(lmGroups[i]+".xml", gCachePathBakedTexturesScene + "/lightmap_" + lmGroups[i] + ".png" );
}
for (int i=0; i < filesShortNames.length; ++i)
{
ImportLightmappedModel(filesShortNames[i], worldPositions[i], lmGroups[i]);
}
log.Info("ImportBakedData -> end()");
return true;
}
Вручную-то и я могу сохранять, даже могу переопределить Serializable::LoadXML() и Serializable::SaveXML(), и читать/писать в том формате, который мне удобен, но раз уж есть стандартные средства, которые должны работать, то хотелось бы использовать их. Вот и пытаюсь понять, это где-то в движке баг, или я чего-то не догоняю... Судя по коду в Serializable::SaveXML() всё должно работать:
+ Показать
− Скрыть
const Vector<AttributeInfo>* attributes = GetAttributes();
if (!attributes)
return true;
Variant value;
for (unsigned i = 0; i < attributes->Size(); ++i)
{
const AttributeInfo& attr = attributes->At(i);
if (!(attr.mode_ & AM_FILE) || (attr.mode_ & AM_FILEREADONLY) == AM_FILEREADONLY)
continue;
OnGetAttribute(attr, value);
Variant defaultValue(GetAttributeDefault(i));
if (value == defaultValue && !SaveDefaultAttributes())
continue;
XMLElement attrElem = dest.CreateChild("attribute");
attrElem.SetAttribute("name", attr.name_);
if (attr.enumNames_)
{
int enumValue = value.GetInt();
attrElem.SetAttribute("value", attr.enumNames_[enumValue]);
}
else
attrElem.SetVariantValue(value);
}
Похоже, имя XMLElement'у добавляется в куске
if (attr.enumNames_)
{
int enumValue = value.GetInt();
attrElem.SetAttribute("value", attr.enumNames_[enumValue]);
}
else
attrElem.SetVariantValue(value);
где,
— тот самый список имён элементов, входящих в список. Что ему не хватает? Имена есть, а он их всё равно не пишет...
Так что, никто не знает, почему не пишутся имена? Версия движка - пересобранная 1.7.1. Пришлось собирать самому, т.к. нужно было добавить пару нужных мне вещей в компонент RaycastVehicle, но сериализацию я не трогал.
>Так что, никто не знает, почему не пишутся имена?
сорян, наверно просто никто им уже не пользуется среди местных(
спроси на офф форуме https://discourse.urho3d.io
Это как последнее средство, т.к. хотелось бы получить ответ на русском языке. Может, какие-нибудь контакты 1vanK остались, может он что скажет?
Покопался в исходниках. Похоже, VariantVector так и сериализируется без названий аттрибутов, но зачем тогда этот список названий, если толку от него никакого? Непонятно...