/// <summary> /// Creates a list from the data entries in a cache table, using the given where clause and predicate. /// </summary> public static List <T> BuildListFromTable <T>(string connectionString, string table, WhereClause where, Func <CacheReader, T> func) { List <T> list = new List <T>(); using (SqliteConnection db = new SqliteConnection(connectionString)) { db.Open(); // Check how large the result set will be so we're not constantly // Reallocating the array. string query = "select count(*) from " + table + " "; if (where != null) { query += where.GetSql(); } using (SqliteCommand cmd = new SqliteCommand(query, db)) { if (where != null) { where.AddParameters(cmd); } int val = (int)(long)cmd.ExecuteScalar(); list = new List <T>(val); } // Set up the actual full query. query = "select * from " + table; if (where != null) { query += where.GetSql(); } using (SqliteCommand cmd = new SqliteCommand(query, db)) { if (where != null) { where.AddParameters(cmd); } using (CacheReader reader = new CacheReader(cmd.ExecuteReader())) { while (reader.NextRow()) { try { list.Add(func(reader)); } catch (Exception) { throw; } } } } } return(list); }
internal static CacheReader CreateReader(SourcePackage upk, string filename) { var r = new CacheReader(upk, filename); r.VerifyMagic(Magic); return(r); }
public static UxlDefine Read(CacheReader f) { var name = f.ReadGlobalString(); var cond = f.ReadGlobalValue(); return(new UxlDefine(name, cond)); }
public static ImageFile ReadImageFile(this CacheReader f) { var flags = (UxlImageFileFlags)f.ReadByte(); var srcName = f.ReadGlobalValue(); SourceValue?dstName = null , cond = null; if (flags.HasFlag(UxlImageFileFlags.HasCondition)) { cond = f.ReadGlobalValue(); } if (flags.HasFlag(UxlImageFileFlags.HasTargetName)) { dstName = f.ReadGlobalValue(); } int?w = null, h = null; if (flags.HasFlag(UxlImageFileFlags.HasTargetWidth)) { w = f.ReadCompressedInt(); } if (flags.HasFlag(UxlImageFileFlags.HasTargetHeight)) { h = f.ReadCompressedInt(); } return(new ImageFile(srcName, cond, dstName, w, h)); }
/// <summary> /// 查询并填充子类信息 /// </summary> /// <param name="pks"></param> /// <param name="mappingInfo"></param> /// <param name="dicEntity"></param> /// <param name="dao"></param> /// <param name="lstParamNames"></param> /// <param name="db"></param> /// <param name="curObjs"></param> /// <param name="filter"></param> private static void FillChildReader(Queue <object> pks, EntityMappingInfo mappingInfo, Dictionary <string, List <object> > dicEntity, BQLDbBase dao, ref List <EntityPropertyInfo> lstParamNames, DBInfo db, Queue <object> curObjs, ScopeList filter) { EntityInfoHandle childInfo = mappingInfo.TargetProperty.BelongInfo; string fullName = mappingInfo.TargetProperty.BelongInfo.EntityType.FullName; Type childType = mappingInfo.TargetProperty.BelongInfo.EntityType; List <object> senders = null; while (pks.Count > 0) { Queue <object> searchPks = GetSearchPKs(pks); if (searchPks.Count <= 0) { break; } ScopeList lstScope = new ScopeList(); lstScope.AddScopeList(filter); lstScope.AddIn(mappingInfo.TargetProperty.PropertyName, searchPks); using (IDataReader reader = dao.QueryReader(lstScope, childInfo.EntityType)) { //获取子表的get列表 if (lstParamNames == null) { lstParamNames = CacheReader.GenerateCache(reader, childInfo);//创建一个缓存数值列表 } while (reader.Read()) { string fk = reader[mappingInfo.TargetProperty.ParamName].ToString(); if (!dicEntity.TryGetValue(fk, out senders)) { continue; } object obj = childInfo.CreateSelectProxyInstance(); if (curObjs != null) { curObjs.Enqueue(obj); } CacheReader.FillObjectFromReader(reader, lstParamNames, obj, db); foreach (object sender in senders) { if (mappingInfo.IsParent) { mappingInfo.SetValue(sender, obj); } else { IList lst = (IList)mappingInfo.GetValue(sender); lst.Add(obj); } } } } } }
public static UxlDeprecate Read(CacheReader f) { var src = f.ReadSource(); var oldName = f.ReadGlobalString(); var newName = f.ReadGlobalString(); return(new UxlDeprecate(src, oldName, newName)); }
/// <summary> /// Creates a list from the data entries in a cache table, using the given where clause and predicate. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="table"></param> /// <param name="where"></param> /// <param name="func"></param> /// <returns></returns> private async Task <List <T> > BuildListFromTable <T>(string table, WhereClause where, Func <CacheReader, Task <T> > func) { List <T> list = new List <T>(); using (var db = new SQLiteConnection(_connectionString)) { db.Open(); // Check how large the result set will be so we're not constantly // Reallocating the array. var query = "select count(*) from " + table + " "; if (where != null) { query += where.GetSql(); } using (var cmd = new SQLiteCommand(query, db)) { if (where != null) { where.AddParameters(cmd); } int val = (int)((long)await cmd.ExecuteScalarAsync()); list = new List <T>(val); } // Set up the actual full query. query = "select * from " + table; if (where != null) { query += where.GetSql(); } using (var cmd = new SQLiteCommand(query, db)) { if (where != null) { where.AddParameters(cmd); } using (var reader = new CacheReader(cmd.ExecuteReader())) { while (reader.NextRow()) { try { list.Add(await func(reader)); } catch (Exception ex) { throw ex; } } } } } return(list); }
static void Repair(string cachePath) { var streamFile = new FileInfo(Path.Combine(cachePath, CacheFetcher.CacheStreamName)); var checkFile = new FileInfo(Path.Combine(cachePath, CacheFetcher.CachePositionName)); var replace = new FileInfo(Path.Combine(cachePath, CacheFetcher.CachePositionName + ".fix")); var posReader = new FileCheckpointArrayReader(checkFile, 2); var vector = posReader.Read(); var sourceStream = streamFile.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite); var reader = new CacheReader(new FixedCheckpointArrayReader(vector), sourceStream, posReader); var prev = 0L; var pos = 0L; var i = 0L; while (true) { try { var result = reader.ReadAll(pos, 1000, (id, position, maxPosition) => { }); if (result.ReadRecords > 0) { prev = pos; pos = result.CurrentCachePosition; i += 1; if ((i % 100) == 0) { Console.WriteLine("{0}:{1:F1}GB", i, 1F * pos / 1024 / 1024 / 1024); } continue; } Console.WriteLine("We are good"); return; } catch (InvalidStorageFormatException ex) { Console.WriteLine("Last known position {0}", pos); Console.WriteLine("Previous position {0} (-{1} bytes)", prev, pos - prev); var previousBlock = reader.ReadAll(prev, 1); var msg = previousBlock.Messages.Single(); var offset = msg.Message.Id.GetOffset(); Console.WriteLine("Previous offset {0}", offset); var replaceCheck = new FileCheckpointArrayWriter(replace, 2); replaceCheck.GetOrInitPosition(); replaceCheck.Update(new long[] { prev, offset }); Console.WriteLine("Backup written"); } break; } Console.ReadLine(); }
/// <summary> /// 获取缓存中的Reader /// </summary> /// <param name="tables">表</param> /// <param name="sql">SQL语句</param> /// <param name="lstParam">变量集合</param> /// <returns></returns> public IDataReader SetReader(IDataReader reader, IDictionary <string, bool> tables, string sql, ParamList lstParam, DataBaseOperate oper) { if (_cache == null) { return(null); } DataSet ds = CacheReader.GenerateDataSet(reader, false); MemCacheReader mreader = new MemCacheReader(ds); SetDataSet(ds, tables, sql, lstParam, oper); return(mreader); }
public static UxlElement Read(CacheReader f) { var flags = (UxlElementFlags)f.ReadByte(); var key = f.ReadGlobalValue(); var value = f.ReadGlobalValue(); SourceValue?cond = null; if (flags.HasFlag(UxlElementFlags.HasCondition)) { cond = f.ReadGlobalValue(); } return(new UxlElement((UxlElementType)(flags & UxlElementFlags.TypeMask), key, value, cond, flags.HasFlag(UxlElementFlags.IsDefault))); }
public static UxlImplementation Read(CacheReader r) { var flags = (UxlImplementationFlags)r.ReadByte(); var src = r.ReadSource(); var body = r.ReadGlobalValue(); SourceValue?cond = null; if (flags.HasFlag(UxlImplementationFlags.HasCondition)) { cond = r.ReadGlobalValue(); } return(new UxlImplementation(src, (ImplementationType)(flags & UxlImplementationFlags.TypeMask), body, cond, flags.HasFlag(UxlImplementationFlags.IsDefault))); }
protected void ReadEntity(CacheReader f, UxlEntityFlags flags) { if (flags.HasFlag(UxlEntityFlags.Elements)) { f.ReadList(Elements, UxlElement.Read); } if (flags.HasFlag(UxlEntityFlags.CopyFiles)) { f.ReadList(CopyFiles, r => f.ReadCopyFile()); } if (flags.HasFlag(UxlEntityFlags.ImageFiles)) { f.ReadList(ImageFiles, r => f.ReadImageFile()); } }
public static UxlDeclare Read(CacheReader f) { var flags = (UxlDeclareFlags)f.ReadByte(); var src = f.ReadSource(); var key = f.ReadGlobalValue(); SourceValue?cond = null; if (flags.HasFlag(UxlDeclareFlags.HasCondition)) { cond = f.ReadGlobalValue(); } return(new UxlDeclare(src, (UxlDeclareType)(flags & UxlDeclareFlags.TypeMask), key, cond)); }
public static UxlTemplate Read(CacheReader f) { var flags = (UxlTemplateFlags)f.ReadByte(); SourceValue?cond = null; if (flags.HasFlag(UxlTemplateFlags.HasCondition)) { cond = f.ReadGlobalValue(); } var result = new UxlTemplate(f.ReadGlobalValue(), cond, flags.HasFlag(UxlTemplateFlags.IsDefault)); result.ReadEntity(f, (UxlEntityFlags)flags); return(result); }
/// <summary> /// 查询并且返回DataSet(游标分页) /// </summary> /// <param name="sql">要查询的SQL语句</param> /// <param name="objPage">分页对象</param> /// <param name="oper">数据库对象</param> /// <param name="curType">映射的实体类型(如果用回数据库的原列名,则此为null)</param> /// <returns></returns> public static DataTable QueryDataTable(string sql, PageContent objPage, DataBaseOperate oper, Type curType) { DataTable ret = new DataTable(); ParamList lstParams = new ParamList(); lstParams.AddNew("@sql", DbType.AnsiString, sql); lstParams.AddNew("@currentIndex", DbType.Int32, objPage.GetStarIndex() + 1); lstParams.AddNew("@pagesize", DbType.Int32, objPage.PageSize); lstParams.AddNew("@maxRecords", DbType.Int64, objPage.MaxSelectRecords); IDataReader reader = null; try { InitProc(oper); reader = oper.Query(ProcName, lstParams, CommandType.StoredProcedure, null); if (reader.NextResult())//第二个结果集为查询结果 { if (curType == null) { ret = CacheReader.GenerateDataTable(reader, "newDt", false); } else { ret = CacheReader.GenerateDataTable(reader, "newDt", curType, false); } } if (reader.NextResult())//第三个结果集为总行数 { if (reader.Read()) { int totalRecord = reader.GetInt32(0); objPage.TotalRecords = totalRecord; //int totalPage = (int)Math.Ceiling((double)objPage.TotalRecords / (double)objPage.PageSize); //objPage.TotalPage = totalPage; if (objPage.CurrentPage >= objPage.TotalPage - 1) { objPage.CurrentPage = objPage.TotalPage - 1; } } } } finally { reader.Close(); } return(ret); }
private void ReadItemGroups() { using (var reader = new CacheReader(this)) { // NOTE: Order (alphabetical by group name followed by log messages) must match writer. Analyzers = reader.ReadItemGroup(); CompileTimeAssemblies = reader.ReadItemGroup(); ContentFilesToPreprocess = reader.ReadItemGroup(); FrameworkAssemblies = reader.ReadItemGroup(); NativeLibraries = reader.ReadItemGroup(); ResourceAssemblies = reader.ReadItemGroup(); RuntimeAssemblies = reader.ReadItemGroup(); RuntimeTargets = reader.ReadItemGroup(); TransitiveProjectReferences = reader.ReadItemGroup(); _logMessages = reader.ReadItemGroup(); } }
public static UxlDocument Read(CacheReader f, SourcePackage upk) { var backend = (UxlBackendType)f.ReadByte(); var flags = (UxlDocumentFlags)f.ReadByte(); SourceValue?cond = null; if (flags.HasFlag(UxlDocumentFlags.HasCondition)) { cond = f.ReadGlobalValue(); } var doc = new UxlDocument(upk, backend, cond); if (flags.HasFlag(UxlDocumentFlags.Defines)) { f.ReadList(doc.Defines, UxlDefine.Read); } if (flags.HasFlag(UxlDocumentFlags.Usings)) { f.ReadList(doc.Usings, r => r.ReadGlobalValue()); } if (flags.HasFlag(UxlDocumentFlags.Declarations)) { f.ReadList(doc.Declarations, UxlDeclare.Read); } if (flags.HasFlag(UxlDocumentFlags.Deprecations)) { f.ReadList(doc.Deprecations, UxlDeprecate.Read); } if (flags.HasFlag(UxlDocumentFlags.Templates)) { f.ReadList(doc.Templates, UxlTemplate.Read); } if (flags.HasFlag(UxlDocumentFlags.Types)) { f.ReadList(doc.Types, UxlType.Read); } var entityFlags = (UxlEntityFlags)f.ReadByte(); doc.ReadEntity(f, entityFlags); return(doc); }
/* * Default Required To Initialize the MainAsync() method. */ public static void Main(string[] args) { Program p = new Program(); int length = (int)CacheReader.Open(); cache = CacheReader.SeekCache(0, length, length + 8192); CacheReader.Close(); Task task = p.MainAsync(); System.Runtime.CompilerServices.TaskAwaiter await = task.GetAwaiter(); try { await.GetResult(); } catch (Exception e) { Console.WriteLine(e.ToString()); } }
/// <summary> /// 查询并且返回DataSet(游标分页) /// </summary> /// <param name="sql">要查询的SQL语句</param> /// <param name="lstParam">参数集合</param> /// <param name="objPage">分页对象</param> /// <param name="oper">数据库对象</param> /// <param name="curType">映射的实体类型(如果用回数据库的原列名,则此为null)</param> /// <returns></returns> public static DataTable QueryDataTable(string sql, ParamList lstParam, PageContent objPage, DataBaseOperate oper, Type curType, Dictionary <string, bool> cacheTables) { objPage.TotleRecords = CutPageSqlCreater.GetTotleRecord(lstParam, oper, sql, objPage.MaxSelectRecords, cacheTables); long totlePage = (long)Math.Ceiling((double)objPage.TotleRecords / (double)objPage.PageSize); objPage.TotlePage = totlePage; if (objPage.CurrentPage >= objPage.TotlePage - 1) { objPage.CurrentPage = objPage.TotlePage - 1; } if (objPage.CurrentPage >= objPage.TotlePage - 1) { objPage.CurrentPage = objPage.TotlePage - 1; } DataTable ret = new DataTable(); IDataReader reader = null; try { string qsql = CutPageSqlCreater.GetCutPageSql(sql, objPage); reader = oper.Query(qsql, lstParam, cacheTables); if (curType == null) { ret = CacheReader.GenerateDataTable(reader, "newDt", false); } else { ret = CacheReader.GenerateDataTable(reader, "newDt", curType, false); } } finally { reader.Close(); //oper.CloseDataBase(); } return(ret); }
public static UxlType Read(CacheReader f) { var flags = (UxlTypeFlags)f.ReadByte(); var name = f.ReadGlobalValue(); SourceValue?cond = null; if (flags.HasFlag(UxlTypeFlags.HasCondition)) { cond = f.ReadGlobalValue(); } var result = new UxlType(name, cond, flags.HasFlag(UxlTypeFlags.IsDefault)); if (flags.HasFlag(UxlTypeFlags.Methods)) { f.ReadList(result.Methods, UxlMethod.Read); } result.ReadEntity(f, (UxlEntityFlags)flags); return(result); }
public static UxlMethod Read(CacheReader f) { var flags = (UxlMethodFlags)f.ReadByte(); var sig = f.ReadGlobalValue(); SourceValue?cond = null; if (flags.HasFlag(UxlMethodFlags.HasCondition)) { cond = f.ReadGlobalValue(); } var result = new UxlMethod(sig, cond, flags.HasFlag(UxlMethodFlags.IsDefault)); if (flags.HasFlag(UxlMethodFlags.Implementations)) { f.ReadList(result.Implementations, UxlImplementation.Read); } result.ReadEntity(f, (UxlEntityFlags)flags); return(result); }
public static CopyFile ReadCopyFile(this CacheReader f) { var flags = (UxlCopyFileFlags)f.ReadByte(); var srcName = f.ReadGlobalValue(); SourceValue?dstName = null , cond = null , type = null; if (flags.HasFlag(UxlCopyFileFlags.HasTargetName)) { dstName = f.ReadGlobalValue(); } if (flags.HasFlag(UxlCopyFileFlags.HasCondition)) { cond = f.ReadGlobalValue(); } if (flags.HasFlag(UxlCopyFileFlags.HasType)) { type = f.ReadGlobalValue(); } return(new CopyFile(srcName, (CopyFileFlags)(flags & UxlCopyFileFlags.FlagsMask), dstName, cond, type)); }
/// <summary> /// 从DataReader加载 /// </summary> /// <param name="reader"></param> public void LoadFromReader(IDataReader reader) { EntityInfoHandle entityInfo = EntityInfoManager.GetEntityHandle(CH.GetRealType(this)); CacheReader.FillInfoFromReader(reader, entityInfo, this); }
/// <summary> /// 从Reader里边读取数据 /// </summary> /// <typeparam name="T">类型</typeparam> /// <param name="reader">reader</param> /// <returns></returns> protected List <T> LoadFromReaderList(IDataReader reader) { return(CacheReader.LoadFormReaderList <T>(reader)); }
/// <summary> /// 从Reader里边读取数据 /// </summary> /// <typeparam name="T">类型</typeparam> /// <param name="reader">reader</param> /// <returns></returns> protected T LoadFromReader(IDataReader reader) { return(CacheReader.LoadFormReader <T>(reader, CurEntityInfo));; }
/// <summary> /// Loads a TTModel file from a given SQLite3 DB filepath. /// </summary> public static TTModel FromDb(FileInfo file, Action <bool, string> loggingFunction = null) { if (loggingFunction == null) { loggingFunction = ModelModifiers.NoOp; } string connectionString = "Data Source=" + file + ";"; TTModel model = new TTModel(); model.Source = file.FullName; // Spawn a DB connection to do the raw queries. using (SqliteConnection db = new SqliteConnection(connectionString)) { db.Open(); // Load Mesh Groups string query = "select * from meshes order by mesh asc;"; using (SqliteCommand cmd = new SqliteCommand(query, db)) { using (CacheReader reader = new CacheReader(cmd.ExecuteReader())) { while (reader.NextRow()) { int meshNum = reader.GetInt32("mesh"); // Spawn mesh groups as needed. while (model.MeshGroups.Count <= meshNum) { model.MeshGroups.Add(new TTMeshGroup()); } model.MeshGroups[meshNum].Name = reader.GetString("name"); } } } // Load Mesh Parts query = "select * from parts order by mesh asc, part asc;"; using (SqliteCommand cmd = new SqliteCommand(query, db)) { using (CacheReader reader = new CacheReader(cmd.ExecuteReader())) { while (reader.NextRow()) { int meshNum = reader.GetInt32("mesh"); int partNum = reader.GetInt32("part"); // Spawn mesh groups if needed. while (model.MeshGroups.Count <= meshNum) { model.MeshGroups.Add(new TTMeshGroup()); } // Spawn parts as needed. while (model.MeshGroups[meshNum].Parts.Count <= partNum) { model.MeshGroups[meshNum].Parts.Add(new TTMeshPart()); } model.MeshGroups[meshNum].Parts[partNum].Name = reader.GetString("name"); } } } // Load Bones query = "select * from bones where mesh >= 0 order by mesh asc, bone_id asc;"; using (SqliteCommand cmd = new SqliteCommand(query, db)) { using (CacheReader reader = new CacheReader(cmd.ExecuteReader())) { while (reader.NextRow()) { int meshId = reader.GetInt32("mesh"); model.MeshGroups[meshId].Bones.Add(reader.GetString("name")); } } } } // Loop for each part, to populate their internal data structures. for (int mId = 0; mId < model.MeshGroups.Count; mId++) { TTMeshGroup m = model.MeshGroups[mId]; for (int pId = 0; pId < m.Parts.Count; pId++) { TTMeshPart p = m.Parts[pId]; WhereClause where = new WhereClause(); WhereClause mWhere = new WhereClause(); mWhere.Column = "mesh"; mWhere.Value = mId; WhereClause pWhere = new WhereClause(); pWhere.Column = "part"; pWhere.Value = pId; where.Inner.Add(mWhere); where.Inner.Add(pWhere); // Load Vertices // The reader handles coalescing the null types for us. p.Vertices = BuildListFromTable(connectionString, "vertices", where, (reader) => { TTVertex vertex = new TTVertex(); // Positions vertex.Position.X = reader.GetFloat("position_x"); vertex.Position.Y = reader.GetFloat("position_y"); vertex.Position.Z = reader.GetFloat("position_z"); // Normals vertex.Normal.X = reader.GetFloat("normal_x"); vertex.Normal.Y = reader.GetFloat("normal_y"); vertex.Normal.Z = reader.GetFloat("normal_z"); // Vertex Colors - Vertex color is RGBA vertex.VertexColor[0] = (byte)Math.Round(reader.GetFloat("color_r") * 255); vertex.VertexColor[1] = (byte)Math.Round(reader.GetFloat("color_g") * 255); vertex.VertexColor[2] = (byte)Math.Round(reader.GetFloat("color_b") * 255); vertex.VertexColor[3] = (byte)Math.Round(reader.GetFloat("color_a") * 255); // UV Coordinates vertex.UV1.X = reader.GetFloat("uv_1_u"); vertex.UV1.Y = reader.GetFloat("uv_1_v"); vertex.UV2.X = reader.GetFloat("uv_2_u"); vertex.UV2.Y = reader.GetFloat("uv_2_v"); // Bone Ids vertex.BoneIds[0] = (byte)reader.GetByte("bone_1_id"); vertex.BoneIds[1] = (byte)reader.GetByte("bone_2_id"); vertex.BoneIds[2] = (byte)reader.GetByte("bone_3_id"); vertex.BoneIds[3] = (byte)reader.GetByte("bone_4_id"); // Weights vertex.Weights[0] = (byte)Math.Round(reader.GetFloat("bone_1_weight") * 255); vertex.Weights[1] = (byte)Math.Round(reader.GetFloat("bone_2_weight") * 255); vertex.Weights[2] = (byte)Math.Round(reader.GetFloat("bone_3_weight") * 255); vertex.Weights[3] = (byte)Math.Round(reader.GetFloat("bone_4_weight") * 255); return(vertex); }); p.TriangleIndices = BuildListFromTable(connectionString, "indices", where, (reader) => { try { return(reader.GetInt32("vertex_id")); } catch (Exception ex) { throw ex; } }); } } // Spawn a DB connection to do the raw queries. using (SqliteConnection db = new SqliteConnection(connectionString)) { db.Open(); // Load Shape Verts string query = "select * from shape_vertices order by shape asc, mesh asc, part asc, vertex_id asc;"; using (SqliteCommand cmd = new SqliteCommand(query, db)) { using (CacheReader reader = new CacheReader(cmd.ExecuteReader())) { while (reader.NextRow()) { string shapeName = reader.GetString("shape"); int meshNum = reader.GetInt32("mesh"); int partNum = reader.GetInt32("part"); int vertexId = reader.GetInt32("vertex_id"); TTMeshPart part = model.MeshGroups[meshNum].Parts[partNum]; // Copy the original vertex and update position. TTVertex vertex = (TTVertex)part.Vertices[vertexId].Clone(); vertex.Position.X = reader.GetFloat("position_x"); vertex.Position.Y = reader.GetFloat("position_y"); vertex.Position.Z = reader.GetFloat("position_z"); TTVertex repVert = part.Vertices[vertexId]; if (repVert.Position.Equals(vertex.Position)) { // Skip morphology which doesn't actually change anything. continue; } if (!part.ShapeParts.ContainsKey(shapeName)) { TTShapePart shpPt = new TTShapePart(); shpPt.Name = shapeName; part.ShapeParts.Add(shapeName, shpPt); } part.ShapeParts[shapeName].VertexReplacements.Add(vertexId, part.ShapeParts[shapeName].Vertices.Count); part.ShapeParts[shapeName].Vertices.Add(vertex); } } } } // Convert the model to FFXIV's internal weirdness. ModelModifiers.MakeImportReady(model, loggingFunction); return(model); }