/// <summary> /// Читает свойство FBX со специальным типом данных после прочтения кода типа данных /// /// Если свойство строковое, то /// Читает строку в UTF-8 по переданной длине в байтах. /// Если строка содержит заголовок Model, то /// Если имя модели не пустое /// (самая первая модель называется Environment и соответстует корневому узлу в navis), /// то редактирует согласно очереди. /// /// Записывает изменение длины строки в байтах /// Если заголовка Model нет или свойство не строковое или это узел без имени, то переписывает без изменений /// </summary> /// <param name="br"></param> /// <param name="bytesCount"></param> /// <param name="addToEnd"></param> /// <returns></returns> private void ReadFBXPropWithSpecialDataTypeEditModelName (BinaryReader br, BinaryWriter bw, bool isString, OffsetCounter offsetCounter) { int len = br.ReadInt32(); if (isString) { byte[] value = br.ReadBytes(len);//Строка в UTF-8 string str = System.Text.Encoding.UTF8.GetString(value); bool changes = false; if (replacements.Count > 0 && str.EndsWith("\0\u0001Model") /*&& str.Length > 7*/) { //Это свойство с именем модели string modelName = str.Replace("\0\u0001Model", ""); //Последовательность узлов моделей, которые подлежат переименованию //начинается только после узла, у которого имя совпадает if (!renamingModelsStarted) { NameReplacement firstElem = replacements.Peek(); NameReplacement secondElem = replacements.Count > 1 ? replacements.ElementAt(1) : null; if ( //modelName.Equals("Environment")//УЗЕЛ Environment ЕСТЬ НЕ ВСЕГДА!!! В каких случаях его нет пока не понятно. firstElem.OldName.Equals(modelName) ) { renamingModelsStarted = true; } else if (secondElem != null && secondElem.OldNameTrustable && secondElem.OldName.Equals(modelName)) { // На всякий случай проверяем второй элемент в очереди (возможно 1-й вообще не появится в FBX?) renamingModelsStarted = true; replacements.Dequeue();//Удаляем узел, который должен был соответствовать Environment } } if (renamingModelsStarted) { bool editAllowed = true; #region hardcode //hardcode//hardcode//hardcode//hardcode//hardcode//hardcode //Замечено, что иногда при экспорте один узел Navis //разбивается на несколько вложенных в FBX (они назывались "curve " и номер) //if (strVal.StartsWith("curve ")) //{ // editAllowed = false; //} //else //{ // curveSequenceStarted = false; //} //hardcode//hardcode//hardcode//hardcode//hardcode//hardcode #endregion //Более гибко - добавить сопоставление имен там, где оно надежно //Это защищает от большинства узлов, которых не было в Navis, но они появились в FBX NameReplacement currReplacement = replacements.Peek(); if (currReplacement.OldNameTrustable) { if (!modelName.Equals(currReplacement.OldName)) { editAllowed = false; } } if (editAllowed)//Не вытаскивать больше из очереди если идет последовательность несопоставляемых узлов { currReplacement = replacements.Dequeue(); if (!currReplacement.SkipNode) { changes = true; //Строка редактируется, длина строки меняется string strEdited = currReplacement.NewName + "\0\u0001Model"; byte[] newValue = Encoding.UTF8.GetBytes(strEdited); int newLen = newValue.Length; int lenDiff = newLen - len; offsetCounter.Incr(lenDiff); bw.Write(newLen); bw.Write(newValue); } } } } if (!changes) { //Ничего не меняется bw.Write(len); bw.Write(value); } } else { //Ничего не меняется bw.Write(len); ReadWriteBytes(br, bw, len); } }
/// <summary> /// Читает строки из текстового FBX /// Если строка содержит не пустое имя модели /// </summary> /// <param name="sw"></param> /// <param name="sr"></param> /// <returns></returns> private string ReplaceNextObjFBXLine(StreamWriter sw, StreamReader sr) { //Найти внутри узла Objects следующий подузел Model //До тех пор пока не найден, нужно записывать каждую строку в новый файл без изменений string fbxLine = null; while (replacements.Count > 0 && (fbxLine = sr.ReadLine()) != null) { bool changes = false; if (regex.IsMatch(fbxLine)) { //Найдена строка с именем объекта string toReplace = regex2.Match(fbxLine).Value; //string modelName = fbxLine.Split(' ')[2];//Пробелы могут быть в самом имени int len = toReplace.Length > 10 ? toReplace.Length - 10 : 0; string modelName = toReplace.Substring(8, len); //Последовательность узлов моделей, которые подлежат переименованию //начинается только после узла, у которого имя совпадает if (!renamingModelsStarted) { NameReplacement firstElem = replacements.Peek(); NameReplacement secondElem = replacements.ElementAt(1); if ( //modelName.Equals("Environment")//УЗЕЛ Environment ЕСТЬ НЕ ВСЕГДА!!! В каких случаях его нет пока не понятно. firstElem.OldName.Equals(modelName) ) { renamingModelsStarted = true; } else if (secondElem.OldNameTrustable && secondElem.OldName.Equals(modelName)) { // На всякий случай проверяем второй элемент в очереди (возможно 1-й вообще не появится в FBX?) renamingModelsStarted = true; replacements.Dequeue();//Удаляем узел, который должен был соответствовать Environment } } if (renamingModelsStarted) { bool editAllowed = true; NameReplacement currReplacement = replacements.Peek(); if (currReplacement.OldNameTrustable) { if (!modelName.Equals(currReplacement.OldName)) { editAllowed = false; } } if (editAllowed) { currReplacement = replacements.Dequeue(); if (!currReplacement.SkipNode) { changes = true; //Строка редактируется string replacement = "\"Model::" + currReplacement.NewName + "\","; string fbxLineEdited = fbxLine.Replace(toReplace, replacement); sw.WriteLine(fbxLineEdited); } } } } if (!changes) { sw.WriteLine(fbxLine); } return(fbxLine); } return(null); }