public Character Build(WowVrcFile file, bool ignoreItemsAndMount = false)
        {
            WowObject characterWowObject;
            var       opts = file.GetOpts();

            if (opts != null)
            {
                if (ignoreItemsAndMount)
                {
                    opts = opts.GetCopy();

                    opts.items = null;
                    opts.mount = null;
                }

                characterWowObject = _exporter.LoadCharacter(WhViewerOptions.FromJson(opts));
            }
            else
            {
                var manualHeader = file.GetManualHeader();
                if (manualHeader == null)
                {
                    throw new System.InvalidOperationException();
                }

                characterWowObject = _exporter.LoadCharacter(manualHeader.Race, manualHeader.Gender, ignoreItemsAndMount ? null : manualHeader.ItemIds);
            }

            // ToDo: грузить все итемы тоже. в viseme editor оно использоваться не будет так как будет передаваться ignoreItems = true, но возможно где-то понадобится

            var res = new Character()
            {
                WowObject = characterWowObject,
                Root      = CreateCharacterGameObjects(characterWowObject)
            };

            return(res);
        }
        public static bool ExportToFbx(this WowVrcFile file, string exportDirectory, bool prepareForVRChat, float scale, out string warnings)
        {
            var exporter = new WowModelExporter();

            WowObject characterWowObject;

            var opts = file.GetOpts();

            if (opts != null)
            {
                characterWowObject = exporter.LoadCharacter(WhViewerOptions.FromJson(opts), scale);
            }
            else
            {
                var manualHeader = file.GetManualHeader();
                if (manualHeader == null)
                {
                    throw new System.InvalidOperationException();
                }

                characterWowObject = exporter.LoadCharacter(manualHeader.Race, manualHeader.Gender, manualHeader.ItemIds, scale);
            }

            // ToDo: после запекания идет привязка на текущие индексы вершин. Если вершины будут перестроены, надо тут тоже обновить индексы
            var bakedBlendshapes = new List <BlendShapeUtility.BakedBlendshape>();

            if (file.Blendshapes != null)
            {
                foreach (var blendshape in file.Blendshapes)
                {
                    if (blendshape.Bones.Length > 0)
                    {
                        if (blendshape.Name == WowVrcFileData.BlendshapeData.basicBlendshapeName)
                        {
                            var basicBakedBlendshape = BlendShapeUtility.BakeBlendShape(characterWowObject.GlobalPosition, characterWowObject.MainMesh.Vertices, characterWowObject.Bones, blendshape.Bones, scale);

                            foreach (var basicBakedBlendshapeElement in basicBakedBlendshape)
                            {
                                characterWowObject.MainMesh.Vertices[basicBakedBlendshapeElement.Key].Position = new Vec3(basicBakedBlendshapeElement.Value.Position.X, basicBakedBlendshapeElement.Value.Position.Y, basicBakedBlendshapeElement.Value.Position.Z);
                                characterWowObject.MainMesh.Vertices[basicBakedBlendshapeElement.Key].Normal   = new Vec3(basicBakedBlendshapeElement.Value.Normal.X, basicBakedBlendshapeElement.Value.Normal.Y, basicBakedBlendshapeElement.Value.Normal.Z);
                            }
                        }
                        else
                        {
                            bakedBlendshapes.Add(new BlendShapeUtility.BakedBlendshape
                            {
                                BlendshapeName = blendshape.Name,
                                Changes        = BlendShapeUtility.BakeBlendShape(characterWowObject.GlobalPosition, characterWowObject.MainMesh.Vertices, characterWowObject.Bones, blendshape.Bones, scale)
                            });
                        }
                    }
                }
            }

            if (prepareForVRChat)
            {
                warnings = PrepareForVRChatUtility.PrepareObject(characterWowObject, bakedBlendshapes, scale,
                                                                 true, true, true, true, true, true);
            }
            else
            {
                warnings = null;
            }

            var fbxExporter = new Exporter();

            return(fbxExporter.ExportWowObject(characterWowObject, bakedBlendshapes, exportDirectory, false));
        }