Пример #1
0
        static async Task BatchExportItem(string path, IItemModel item, XivModelInfo secondaryModelInfo, Func <Task <List <XivRace> > > getRaces)
        {
            if (File.Exists(path))
            {
                return;
            }

            WriteLine($"Exporting {item.GetType().Name} {item.Name}: {Path.GetFileNameWithoutExtension(path)}");

            var metadata = new ExportMetadata();

            metadata.Name = item.Name;

            var mdl   = new Mdl(_gameDir, item.DataFile);
            var races = await getRaces();

            foreach (var race in races)
            {
                var mdlData = await mdl.GetMdlData(item, race, secondaryModelInfo);

                var textures = await TexTools.MaterialsHelper.GetMaterials(_gameDir, item, mdlData, race);

                var set = BatchExportSet(mdlData, textures);
                set.Name = TexTools.XivStringRaces.ToRaceGenderName(race);
                metadata.Sets.Add(set);
            }

            var metadataJson = JsonConvert.SerializeObject(metadata);

            File.WriteAllText(path, metadataJson);
        }
        /// <summary>
        /// The event handler for the advanced options button clicked
        /// </summary>
        private async void AdvOptionsButton_Click(object sender, RoutedEventArgs e)
        {
            var selectedItem = ModelTypeComboBox.SelectedItem as ModComboBox;

            var mod = selectedItem.SelectedMod;

            var includedMod = new IncludedMods
            {
                Name     = $"{Path.GetFileNameWithoutExtension(mod.fullPath)} ({((Category)ModListTreeView.SelectedItem).Name})",
                FullPath = mod.fullPath
            };

            var itemModel = MakeItemModel(mod);

            var includedModsList = IncludedModsList.Items.Cast <IncludedMods>().ToList();
            var mdl = new Mdl(_gameDirectory, XivDataFiles.GetXivDataFile(mod.datFile));

            try
            {
                // TODO - Include Submesh ID ?
                // Do we even have any kind of UI To specify this in the wizard?
                // Submeshes are only used for Furniture anyways, so it might be a 'will not fix'
                bool success = await ImportModelView.ImportModel(itemModel, IOUtil.GetRaceFromPath(mod.fullPath), null, this, null, true);

                if (!success)
                {
                    return;
                }
            }
            catch (Exception ex)
            {
                FlexibleMessageBox.Show(ex.Message, UIMessages.AdvancedImportErrorTitle,
                                        MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            var mdlData = ImportModelView.GetData();

            if (includedModsList.Any(item => item.Name.Equals(includedMod.Name)))
            {
                if (FlexibleMessageBox.Show(
                        string.Format(UIMessages.ExistingOption, includedMod.Name),
                        UIMessages.OverwriteTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Question) ==
                    System.Windows.Forms.DialogResult.Yes)
                {
                    _selectedModOption.Mods[mod.fullPath].ModDataBytes = mdlData;
                }
            }
            else
            {
                IncludedModsList.Items.Add(includedMod);
                _selectedModOption.Mods.Add(mod.fullPath, new ModData
                {
                    Name         = mod.name,
                    Category     = mod.category,
                    FullPath     = mod.fullPath,
                    ModDataBytes = mdlData,
                });
            }
        }
Пример #3
0
        /// <summary>
        /// The event handler for the advanced options button clicked
        /// </summary>
        private async void AdvOptionsButton_Click(object sender, RoutedEventArgs e)
        {
            var selectedFile = ModelTypeComboBox.SelectedItem as FileEntry;
            var itemModel    = (IItemModel)SelectedItem;
            var mdl          = new Mdl(_gameDirectory, IOUtil.GetDataFileFromPath(selectedFile.Path));

            try
            {
                // TODO - Include Submesh ID ?
                // Do we even have any kind of UI To specify this in the wizard?
                // Submeshes are only used for Furniture anyways, so it might be a 'will not fix'
                bool success = await ImportModelView.ImportModel(itemModel, IOUtil.GetRaceFromPath(selectedFile.Path), null, this, null, true);

                if (!success)
                {
                    return;
                }
            }
            catch (Exception ex)
            {
                FlexibleMessageBox.Show(ex.Message, UIMessages.AdvancedImportErrorTitle,
                                        MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            var mdlData = ImportModelView.GetData();

            AddFile(selectedFile, SelectedItem, mdlData);
        }
        /// <summary>
        /// The event handler for the custom model button clicked
        /// </summary>
        private async void AddCustomModelButton_Click(object sender, RoutedEventArgs e)
        {
            var selectedItem = ModelTypeComboBox.SelectedItem as ModComboBox;

            var mod = selectedItem.SelectedMod;

            var includedMod = new IncludedMods
            {
                Name     = $"{Path.GetFileNameWithoutExtension(mod.fullPath)} ({((Category)ModListTreeView.SelectedItem).Name})",
                FullPath = mod.fullPath
            };

            var itemModel = MakeItemModel(mod);

            var includedModsList = IncludedModsList.Items.Cast <IncludedMods>().ToList();
            var mdl    = new Mdl(_gameDirectory, XivDataFiles.GetXivDataFile(mod.datFile));
            var xivMdl = await mdl.GetMdlData(itemModel, GetRace(mod.fullPath), null, null, mod.data.originalOffset);

            var warnings = await mdl.ImportModel(itemModel, xivMdl, new DirectoryInfo(CustomModelTextBox.Text), null, XivStrings.TexTools,
                                                 Settings.Default.DAE_Plugin_Target, true);

            if (warnings.Count > 0)
            {
                foreach (var warning in warnings)
                {
                    FlexibleMessageBox.Show(
                        $"{warning.Value}", $"{warning.Key}",
                        MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }
            }

            var mdlData = mdl.MDLRawData;

            if (includedModsList.Any(item => item.Name.Equals(includedMod.Name)))
            {
                if (FlexibleMessageBox.Show(
                        string.Format(UIMessages.ExistingOption, includedMod.Name),
                        UIMessages.OverwriteTitle, MessageBoxButtons.YesNo, MessageBoxIcon.Question) ==
                    System.Windows.Forms.DialogResult.Yes)
                {
                    _selectedModOption.Mods[mod.fullPath].ModDataBytes = mdlData;
                }
            }
            else
            {
                IncludedModsList.Items.Add(includedMod);
                _selectedModOption.Mods.Add(mod.fullPath, new ModData
                {
                    Name         = mod.name,
                    Category     = mod.category,
                    FullPath     = mod.fullPath,
                    ModDataBytes = mdlData
                });
            }
        }
Пример #5
0
        public void MdlInitialize()
        {
            treeView1.Nodes.Clear();
            TreeNode tn1 = new TreeNode("0");
            Mdl      mdl = Mdls.Single(m => m.parentcode == "0");

            tn1.Tag  = mdl;
            tn1.Text = mdl.form;
            treeView1.Nodes.Add(tn1);
            this.Bind(tn1);
            treeView1.Font = new Font("宋体", 15, FontStyle.Bold);
            treeView1.ExpandAll();
        }
Пример #6
0
 /// <summary>
 /// Método para editar um registro
 /// </summary>
 /// <param name="mdl"></param>
 public void Update(Mdl mdl)
 {
     try
     {
         AbrirConexão();
         ExecuteNonQuery(GetSqlUpdate(mdl));
     }
     catch (Exception ex)
     {
         MessageBox.Show("Houve um erro: \n" + ex);
     }
     finally
     {
         FecharConexao();
     }
 }
        /// <summary>
        /// The event handler for the advanced options button clicked
        /// </summary>
        private void AdvOptionsButton_Click(object sender, RoutedEventArgs e)
        {
            var selectedItem = ModelTypeComboBox.SelectedItem as ModComboBox;

            var mod = selectedItem.SelectedMod;

            var includedMod = new IncludedMods
            {
                Name     = $"{Path.GetFileNameWithoutExtension(mod.fullPath)} ({((Category)ModListTreeView.SelectedItem).Name})",
                FullPath = mod.fullPath
            };

            var itemModel = MakeItemModel(mod);

            var includedModsList = IncludedModsList.Items.Cast <IncludedMods>().ToList();
            var mdl = new Mdl(_gameDirectory, XivDataFiles.GetXivDataFile(mod.datFile));

            var xivMdl = mdl.GetMdlData(itemModel, GetRace(mod.fullPath), null, null, mod.data.originalOffset);

            var advancedImportView = new AdvancedModelImportView(xivMdl, itemModel, GetRace(mod.fullPath), true);
            var result             = advancedImportView.ShowDialog();

            if (result == true)
            {
                if (includedModsList.Any(item => item.Name.Equals(includedMod.Name)))
                {
                    if (FlexibleMessageBox.Show(
                            $"This Option already includes {includedMod.Name}  \n\n Would you like to overwrite the existing mod for this option?",
                            "Overwrite?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) ==
                        System.Windows.Forms.DialogResult.Yes)
                    {
                        _selectedModOption.Mods[mod.fullPath].ModDataBytes = advancedImportView.RawModelData;
                    }
                }
                else
                {
                    IncludedModsList.Items.Add(includedMod);
                    _selectedModOption.Mods.Add(mod.fullPath, new ModData
                    {
                        Name         = mod.name,
                        Category     = mod.category,
                        FullPath     = mod.fullPath,
                        ModDataBytes = advancedImportView.RawModelData
                    });
                }
            }
        }
Пример #8
0
        /// <summary>
        /// The event handler for the custom model button clicked
        /// </summary>
        private void AddCustomModelButton_Click(object sender, RoutedEventArgs e)
        {
            var selectedItem = ModelTypeComboBox.SelectedItem as ModComboBox;

            var mod = selectedItem.SelectedMod;

            var includedMod = new IncludedMods
            {
                Name     = $"{Path.GetFileNameWithoutExtension(mod.fullPath)} ({((Category)ModListTreeView.SelectedItem).Name})",
                FullPath = mod.fullPath
            };

            var itemModel = MakeItemModel(mod);

            var includedModsList = IncludedModsList.Items.Cast <IncludedMods>().ToList();
            var mdl           = new Mdl(_gameDirectory, XivDataFiles.GetXivDataFile(mod.datFile));
            var xivMdl        = mdl.GetMdlData(itemModel, GetRace(mod.fullPath));
            var importResults = mdl.ImportModel(itemModel, xivMdl, new DirectoryInfo(CustomModelTextBox.Text), null, XivStrings.TexTools,
                                                true);

            //TODO: Add dialogs for import results (warning messages)

            var mdlData = mdl.MDLRawData;

            if (includedModsList.Any(item => item.Name.Equals(includedMod.Name)))
            {
                if (FlexibleMessageBox.Show(
                        $"This Option already includes {includedMod.Name}  \n\n Would you like to overwrite the existing mod for this option?",
                        "Overwrite?", MessageBoxButtons.YesNo, MessageBoxIcon.Question) ==
                    System.Windows.Forms.DialogResult.Yes)
                {
                    _selectedModOption.Mods[mod.fullPath].ModDataBytes = mdlData;
                }
            }
            else
            {
                IncludedModsList.Items.Add(includedMod);
                _selectedModOption.Mods.Add(mod.fullPath, new ModData
                {
                    Name         = mod.name,
                    Category     = mod.category,
                    FullPath     = mod.fullPath,
                    ModDataBytes = mdlData
                });
            }
        }
Пример #9
0
        /// <summary>
        /// Monta o sql de insert
        /// </summary>
        /// <param name="mdl">Model</param>
        /// <returns>Retorna sql para adicionar no banco</returns>
        private string GetSqlInsert(Mdl mdl)
        {
            string sql = $@"INSERT INTO {mdl.GetType().Name} (";

            #region CAMPOS
            bool first = true;
            foreach (var campo in mdl.GetType().GetProperties())
            {
                //Verifica se o campo não é do Mdl (o id fica guardado lá)
                if (campo.DeclaringType.Name != "Mdl")
                {
                    sql  += first ? "" : ", ";
                    first = false;

                    sql += campo.Name;
                }
            }
            #endregion

            sql += $@") VALUES(";

            #region VALUES

            first = true;
            foreach (var campo in mdl.GetType().GetProperties())
            {
                //Verifica se o campo não é do Mdl (o id fica guardado lá)
                if (campo.DeclaringType.Name != "Mdl")
                {
                    sql  += first ? "" : ", ";
                    first = false;

                    sql += "'" + campo.GetValue(mdl, null) + "'";
                }
            }

            #endregion

            sql += ");";

            return(sql);
        }
Пример #10
0
        /// <summary>
        /// Método para excluir um registro
        /// </summary>
        /// <param name="mdl"></param>
        public void Delete(Mdl mdl)
        {
            try
            {
                AbrirConexão();

                string sql = $@"DELETE FROM {mdl.GetType().Name}
                                   WHERE id = {mdl.Id};";

                ExecuteNonQuery(sql);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Houve um erro: \n" + ex);
            }
            finally
            {
                FecharConexao();
            }
        }
Пример #11
0
        private async Task <string> GetInternalSkelName(string fullMdlPath)
        {
            if (IsFurnishing(fullMdlPath))
            {
                return(null);
            }

            var mdlPath  = fullMdlPath;
            var mdlName  = Path.GetFileName(fullMdlPath);
            var skelName = mdlName.Substring(0, 5);

            if (IsHat(fullMdlPath) || IsFace(fullMdlPath))
            {
                skelName = mdlName.Substring(5, 5);
            }
            else if (IsHair(mdlPath))
            {
                // This part sucks, gotta load the MDL and scrape the bone list
                // to look for hair EX bones.
                // No real getting around it until we find out how skeletons are set in game.

                var _mdl  = new Mdl(_gameDirectory, IOUtil.GetDataFileFromPath(fullMdlPath));
                var model = await _mdl.GetModel(fullMdlPath, true);   // Get the OG skel for the hair, don't trick users into thinking they can add EX bones.

                // This process technically should also be done for other gear slots that might have EX Bones.
                // But that's both rare, and this process is expensive, so we don't, and instead just package EX bone sets
                // in with the TexTools distributable.

                if (model.Bones.Any(x => x.Contains("x_h")))
                {
                    var bone = model.Bones.First(x => x.Contains("x_h"));
                    skelName = bone.Substring(bone.IndexOf("x_h") + 2, 5);
                }
                else
                {
                    skelName = mdlName.Substring(5, 5);
                }
            }

            return(skelName);
        }
Пример #12
0
        /// <summary>
        /// Monta o sql de update
        /// </summary>
        /// <param name="mdl">Model</param>
        /// <returns>Retorna sql para editar no banco</returns>
        private string GetSqlUpdate(Mdl mdl)
        {
            string sql = $"UPDATE {mdl.GetType().Name} SET ";

            bool first = true;

            foreach (var campo in mdl.GetType().GetProperties())
            {
                //Verifica se o campo não é do Mdl (o id fica guardado lá)
                if (campo.DeclaringType.Name != "Mdl")
                {
                    sql  += first ? "" : ", ";
                    first = false;

                    sql += campo.Name;
                    sql += " = '" + campo.GetValue(mdl, null) + "'";
                }
            }

            sql += $" WHERE id = {mdl.Id};";

            return(sql);
        }
Пример #13
0
        /// <summary>
        /// Retorna DataTable com todas informações do banco
        /// </summary>
        /// <param name="mdl"></param>
        /// <returns>DataTable com todas informações do banco</returns>
        protected DataTable GetDataTable(Mdl mdl)
        {
            DataTable dt = new DataTable();

            try
            {
                AbrirConexão();

                string sql = $"SELECT * FROM {mdl.GetType().Name};";

                dt = ExecuteDataTable(sql);
            }

            catch (Exception ex)
            {
                MessageBox.Show("Houve um erro: \n" + ex);
            }
            finally
            {
                FecharConexao();
            }
            return(dt);
        }
Пример #14
0
        private async void CopyButton_Click(object sender, RoutedEventArgs e)
        {
            var to   = ToBox.Text;
            var from = FromBox.Text;

            try
            {
                if (string.IsNullOrWhiteSpace(to) || string.IsNullOrWhiteSpace(from))
                {
                    return;
                }
                to   = to.Trim().ToLower();
                from = from.Trim().ToLower();

                if (!to.EndsWith(".mdl") || !from.EndsWith(".mdl"))
                {
                    return;
                }

                var toRoot = await XivCache.GetFirstRoot(to);

                var fromRoot = await XivCache.GetFirstRoot(from);

                var df = IOUtil.GetDataFileFromPath(to);

                var _mdl = new Mdl(XivCache.GameInfo.GameDirectory, df);

                await _mdl.CopyModel(from, to, XivStrings.TexTools, true);

                FlexibleMessageBox.Show("Model Copied Successfully.", "Model Copy Confirmation", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Information);
                Close();
            }
            catch (Exception ex)
            {
                FlexibleMessageBox.Show("Model Copied Failed.\n\nError: " + ex.Message, "Model Copy Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
            }
        }
Пример #15
0
        private void treeView1_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (e.Node.Tag is Mdl)
            {
                Mdl mdl = (Mdl)e.Node.Tag;
                this.panel4.Controls.Clear();
                switch (mdl.form)
                {
                case "FormLogin":
                    FrmLogin formLogin = Program.programContainer.GetExportedValue <FrmLogin>();
                    formLogin.TopLevel = false;
                    formLogin.Dock     = DockStyle.Fill;
                    formLogin.Show();
                    this.panel4.Controls.Add(formLogin);
                    ApplyResource(typeof(FrmLogin));
                    break;

                case "FrmGoodNG":
                    FrmGoodNg frmGoodNG = Program.programContainer.GetExportedValue <FrmGoodNg>();
                    frmGoodNG.TopLevel = false;
                    frmGoodNG.Dock     = DockStyle.Fill;
                    frmGoodNG.Show();
                    this.panel4.Controls.Add(frmGoodNG);
                    ApplyResource(typeof(FrmGoodNg));
                    break;

                case "FrmTsInputEdit":
                    FrmTsInputEdit frmTsInputEdit = Program.programContainer.GetExportedValue <FrmTsInputEdit>();
                    frmTsInputEdit.TopLevel = false;
                    frmTsInputEdit.Dock     = DockStyle.Fill;
                    frmTsInputEdit.Show();
                    this.panel4.Controls.Add(frmTsInputEdit);
                    ApplyResource(typeof(FrmTsInputEdit));
                    break;
                }
            }
        }
Пример #16
0
        private bool Import(string path)
        {
            _mdls.Clear();
            using (var fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {
                IWorkbook workbook;
                var       extension = Path.GetExtension(path);
                if (".xlsx".Equals(extension, StringComparison.CurrentCultureIgnoreCase))
                {
                    workbook = new XSSFWorkbook(fs);
                }
                else
                {
                    workbook = new HSSFWorkbook(fs);
                }

                if (workbook.NumberOfSheets > 0)
                {
                    var sheetAt0 = workbook.GetSheetAt(0);
                    var cou      = sheetAt0.LastRowNum;
                    for (var i = 1; i < cou + 1; i++)
                    {
                        var mdl       = new Mdl();
                        var rowHeader = sheetAt0.GetRow(i);

                        mdl.X     = rowHeader.GetCell(0).NumericCellValue;
                        mdl.Y     = rowHeader.GetCell(1).NumericCellValue;
                        mdl.Z     = rowHeader.GetCell(2).NumericCellValue;
                        mdl.Value = rowHeader.GetCell(3).NumericCellValue;

                        _mdls.Add(mdl);
                    }
                }
            }
            return(true);
        }
Пример #17
0
 public virtual OperationResult AddEntity(Mdl mdl, bool isSave = true)
 {
     return(mdlRepository.Insert(mdl, isSave));
 }
        private static async Task Export(string part, IItemModel item, XivRace desiredRace)
        {
            if (item == null)
            {
                return;
            }

            MainWin.LockProgress.Report($"Exporting {part}: {item.Name}");

            Mdl _mdl = new Mdl(GameDirectory, item.DataFile);

            TTModel model = await _mdl.GetModel(item, desiredRace);

            XivRace modelRace = desiredRace;

            if (model == null)
            {
                List <XivRace> priority = desiredRace.GetModelPriorityList();
                foreach (XivRace newRace in priority)
                {
                    model = await _mdl.GetModel(item, newRace);

                    modelRace = newRace;

                    if (model != null)
                    {
                        break;
                    }
                }
            }

            if (model == null)
            {
                throw new Exception($"Failed to get model for item: {item}");
            }

            if (!Directory.Exists($"/{name}/{part}/"))
            {
                Directory.CreateDirectory($"/{name}/{part}/");
            }

            string path = $"/{name}/{part}/{item.Name}.fbx";

            if (desiredRace != modelRace)
            {
                ApplyDeformers(model, modelRace, desiredRace);
            }

            await _mdl.ExportModel(model, path);

            MainWin.LockProgress.Report($"Converting Normals {part}: {item.Name}");

            string[] normalMaps = Directory.GetFiles(Path.GetDirectoryName(path), "*_n.png");
            foreach (string normalMap in normalMaps)
            {
                string disMap = normalMap.Replace("_n.png", "_dis.png");

                ProcessStartInfo processStartInfo = new ProcessStartInfo();
                processStartInfo.FileName       = "NormalToHeight.exe";
                processStartInfo.Arguments      = $"{normalMap} {disMap} -normalise";
                processStartInfo.CreateNoWindow = true;
                processStartInfo.WindowStyle    = ProcessWindowStyle.Hidden;

                Process proc = Process.Start(processStartInfo);

                while (!proc.HasExited)
                {
                    await Task.Delay(100);
                }
            }
        }
        public async Task <bool> Save()
        {
            if (_metadata == null)
            {
                return(false);
            }
            var success = false;

            try
            {
                await MainWindow.GetMainWindow().LockUi("Updating Metadata");

                await ItemMetadata.SaveMetadata(_metadata, XivStrings.TexTools);

                var _mdl = new Mdl(XivCache.GameInfo.GameDirectory, IOUtil.GetDataFileFromPath(_metadata.Root.Info.GetRootFile()));

                foreach (var kv in _metadata.EqdpEntries)
                {
                    if (kv.Value.bit1 == false)
                    {
                        continue;
                    }
                    if (_original.EqdpEntries[kv.Key].bit1 == true)
                    {
                        continue;
                    }

                    // Here we have a new race, we need to create a model for it.
                    await _mdl.AddRacialModel(_metadata.Root.Info.PrimaryId, _metadata.Root.Info.Slot, kv.Key, XivStrings.TexTools);
                }

                if (_metadata.ImcEntries.Count > 0)
                {
                    var _dat = new Dat(XivCache.GameInfo.GameDirectory);
                    var originalMaterialSetMax = _original.ImcEntries.Select(x => x.MaterialSet).Max();
                    var newMaterialSetMax      = _metadata.ImcEntries.Select(x => x.MaterialSet).Max();

                    if (newMaterialSetMax > originalMaterialSetMax)
                    {
                        // We have new materials to add.

                        // First find the base files to copy. (Just always copy from set 1 for simplicity)
                        var copySource = await _metadata.Root.GetMaterialFiles(1);

                        var item = _metadata.Root.GetFirstItem();

                        for (int i = originalMaterialSetMax + 1; i <= newMaterialSetMax; i++)
                        {
                            foreach (var material in copySource)
                            {
                                var dest = material.Replace("v0001", "v" + i.ToString().PadLeft(4, '0'));

                                await _dat.CopyFile(material, dest, XivStrings.TexTools, false, item);
                            }
                        }
                    }
                }

                success = true;
            } catch (Exception Ex)
            {
                Helpers.FlexibleMessageBox.Show("An Error occured while saving the Metadata: \n" + Ex.Message, "Metadata Error", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error, System.Windows.Forms.MessageBoxDefaultButton.Button1);
            }
            finally
            {
                await MainWindow.GetMainWindow().UnlockUi();
            }

            if (success)
            {
                var mw = MainWindow.GetMainWindow();
                mw.ReloadItem();
            }

            return(success);
        }
        public ImportModelViewModel(ImportModelView view, IItemModel item, XivRace race, string submeshId, bool dataOnly, Action onComplete = null, string lastImportFilePath = null)
        {
            _view               = view;
            _item               = item;
            _race               = race;
            _submeshId          = submeshId;
            _dataOnly           = dataOnly;
            _onComplete         = onComplete;
            _lastImportFilePath = lastImportFilePath;

            if (typeof(XivCharacter) == _item.GetType())
            {
                // Fix up naming scheme for character items to match user expectation.
                var clone = (XivCharacter)((XivCharacter)_item).Clone();
                clone.Name = clone.SecondaryCategory;
                _item      = clone;
            }

            var gameDirectory = new DirectoryInfo(Settings.Default.FFXIV_Directory);
            var saveDirectory = new DirectoryInfo(Settings.Default.Save_Directory);
            var dataFile      = IOUtil.GetDataFileFromPath(_item.GetItemRootFolder());

            _mdl       = new Mdl(gameDirectory, dataFile);
            _importers = _mdl.GetAvailableImporters();

            SetupRaces();


            // We need to explicitly fork this onto a new thread to avoid deadlock.
            Task.Run(AssignPath).Wait();

            var defaultPath = $"{IOUtil.MakeItemSavePath(_item, saveDirectory, _race)}\\3D".Replace("/", "\\");
            var modelName   = Path.GetFileNameWithoutExtension(_internalPath);


            // Scan to see which file type(s) actually exist.
            bool foundValidFile = false;

            // FBX is default, so check that first.
            var startingPath = Path.Combine(defaultPath, modelName) + ".fbx";

            if (File.Exists(startingPath))
            {
                foundValidFile = true;
            }

            if (!foundValidFile)
            {
                foreach (var suffix in _importers)
                {
                    startingPath = Path.Combine(defaultPath, modelName) + "." + suffix;
                    if (File.Exists(startingPath))
                    {
                        foundValidFile = true;
                        break;
                    }
                }
            }

            if (!foundValidFile)
            {
                // Auto-fill the last import file path if the file still exists, otherwise just default to reusing the existing model
                startingPath = File.Exists(_lastImportFilePath) ? _lastImportFilePath : "";
            }


            _view.FileNameTextBox.Text = startingPath;

            // Event Handlers
            _view.SelectFileButton.Click += SelectFileButton_Click;
            _view.ImportButton.Click     += ImportButton_Click;
            _view.EditButton.Click       += EditButton_Click;
            _view.Closing += _view_Closing;
            _view.OverrideRaceButton.Checked   += OverrideRaceButton_Checked;
            _view.OverrideRaceButton.Unchecked += OverrideRaceButton_Unchecked;

            // Default Settings for specific categories, event handlers are added to allow users to opt out of these defaults
            if (item.SecondaryCategory == XivStrings.Face)
            {
                _view.UseOriginalShapeDataButton.IsChecked = Settings.Default.UseOriginalShapeDataForFace;
                _view.UseOriginalShapeDataButton.Click    += UseOriginalShapeDataButton_Clicked;
            }
            if (item.SecondaryCategory == XivStrings.Hair)
            {
                _view.CloneUV1Button.IsChecked = Settings.Default.CloneUV1toUV2ForHair;
                _view.CloneUV1Button.Click    += CloneUV1Button_Clicked;
            }

            var iType = item.GetPrimaryItemType();

            if (iType == xivModdingFramework.Items.Enums.XivItemType.equipment || iType == xivModdingFramework.Items.Enums.XivItemType.accessory || iType == xivModdingFramework.Items.Enums.XivItemType.weapon)
            {
                _view.ForceUVsButton.IsChecked = Settings.Default.ForceUV1QuadrantForGear;
                _view.ForceUVsButton.Click    += ForceUVsButton_Clicked;
            }
        }
        /// <summary>
        /// Exports the model
        /// </summary>
        /// <param name="fullModelName">The name chosen by the user for the full model export</param>
        private async Task Export(string fullModelName)
        {
            var pc = await this.ShowProgressAsync(UIMessages.ExportingFullModelTitle, UIMessages.PleaseStandByMessage);

            var fileFormat     = "fbx";
            var savePath       = new DirectoryInfo(Settings.Default.Save_Directory);
            var outputFilePath = $"{savePath}\\FullModel\\{fullModelName}\\{fullModelName}.{fileFormat}";

            // Create output directory
            Directory.CreateDirectory($"{savePath}\\FullModel\\{fullModelName}");

            var fmViewPortVM = viewport3DX.DataContext as FullModelViewport3DViewModel;

            var converterFolder = Directory.GetCurrentDirectory() + "\\converters\\" + fileFormat;

            Directory.CreateDirectory(converterFolder);
            var dbPath = converterFolder + "\\input.db";

            File.Delete(dbPath);

            // Create the DB where all models will be added and fill the metadata
            fmViewPortVM.shownModels.FirstOrDefault().Value.TtModel.SetFullModelDBMetaData(dbPath, fullModelName);

            // Export the materials for each model and save model to DB
            foreach (var model in fmViewPortVM.shownModels)
            {
                var mtrlVariant = 1;
                try
                {
                    var imc = new Imc(_gameDirectory);
                    mtrlVariant = (await imc.GetImcInfo(model.Value.ItemModel)).MaterialSet;
                }
                catch (Exception ex)
                {
                    // No-op, defaulted to 1.
                }

                await Mdl.ExportMaterialsForModel(model.Value.TtModel, outputFilePath, _gameDirectory, mtrlVariant, _fmvm.SelectedSkeleton.XivRace);

                // Save model to DB
            }

            TTModel.SaveFullToFile(dbPath, _fmvm.SelectedSkeleton.XivRace, fmViewPortVM.shownModels.Select(x => x.Value.TtModel).ToList());

            var proc = new Process
            {
                StartInfo = new ProcessStartInfo
                {
                    FileName  = converterFolder + "\\converter.exe",
                    Arguments = "\"" + dbPath + "\"",
                    RedirectStandardOutput = true,
                    RedirectStandardError  = true,
                    UseShellExecute        = false,
                    WorkingDirectory       = "" + converterFolder + "",
                    CreateNoWindow         = true
                }
            };

            proc.Start();
            proc.WaitForExit();
            var code = proc.ExitCode;

            if (code != 0)
            {
                throw new Exception("Exporter threw error code: " + proc.ExitCode);
            }

            var outputFile = converterFolder + "\\result." + fileFormat;

            // Just move the result file if we need to.
            if (!Path.Equals(outputFilePath, outputFile))
            {
                File.Delete(outputFilePath);
                File.Move(outputFile, outputFilePath);
            }

            await pc.CloseAsync();

            await this.ShowMessageAsync(UIMessages.FullModelExportSuccessTitle, string.Format(UIMessages.FullModelExportSuccessMessage, outputFilePath));
        }
Пример #22
0
        /// <summary>
        /// Copies the entirety of a given root to a new root.
        /// </summary>
        /// <param name="Source">Original Root to copy from.</param>
        /// <param name="Destination">Destination root to copy to.</param>
        /// <param name="ApplicationSource">Application to list as the source for the resulting mod entries.</param>
        /// <returns>Returns a Dictionary of all the file conversion</returns>
        public static async Task <Dictionary <string, string> > CloneRoot(XivDependencyRoot Source, XivDependencyRoot Destination, string ApplicationSource, int singleVariant = -1, string saveDirectory = null, IProgress <string> ProgressReporter = null, IndexFile index = null, ModList modlist = null, ModPack modPack = null)
        {
            if (!IsSupported(Source) || !IsSupported(Destination))
            {
                throw new InvalidDataException("Cannot clone unsupported root.");
            }


            if (ProgressReporter != null)
            {
                ProgressReporter.Report("Stopping Cache Worker...");
            }
            var workerStatus = XivCache.CacheWorkerEnabled;

            XivCache.CacheWorkerEnabled = false;
            try
            {
                var df = IOUtil.GetDataFileFromPath(Source.ToString());

                var _imc     = new Imc(XivCache.GameInfo.GameDirectory);
                var _mdl     = new Mdl(XivCache.GameInfo.GameDirectory, df);
                var _dat     = new Dat(XivCache.GameInfo.GameDirectory);
                var _index   = new Index(XivCache.GameInfo.GameDirectory);
                var _mtrl    = new Mtrl(XivCache.GameInfo.GameDirectory);
                var _modding = new Modding(XivCache.GameInfo.GameDirectory);

                var doSave = false;
                if (index == null)
                {
                    doSave = true;
                    index  = await _index.GetIndexFile(df);

                    modlist = await _modding.GetModListAsync();
                }


                bool locked = _index.IsIndexLocked(df);
                if (locked)
                {
                    throw new Exception("Game files currently in use.");
                }


                if (ProgressReporter != null)
                {
                    ProgressReporter.Report("Analyzing items and variants...");
                }

                // First, try to get everything, to ensure it's all valid.
                ItemMetadata originalMetadata = await GetCachedMetadata(index, modlist, Source, df, _dat);


                var originalModelPaths = await Source.GetModelFiles(index, modlist);

                var originalMaterialPaths = await Source.GetMaterialFiles(-1, index, modlist);

                var originalTexturePaths = await Source.GetTextureFiles(-1, index, modlist);

                var originalVfxPaths = new HashSet <string>();
                if (Imc.UsesImc(Source))
                {
                    var avfxSets = originalMetadata.ImcEntries.Select(x => x.Vfx).Distinct();
                    foreach (var avfx in avfxSets)
                    {
                        var avfxStuff = await ATex.GetVfxPath(Source.Info, avfx);

                        if (String.IsNullOrEmpty(avfxStuff.Folder) || String.IsNullOrEmpty(avfxStuff.File))
                        {
                            continue;
                        }

                        var path = avfxStuff.Folder + "/" + avfxStuff.File;
                        if (index.FileExists(path))
                        {
                            originalVfxPaths.Add(path);
                        }
                    }
                }

                // Time to start editing things.

                // First, get a new, clean copy of the metadata, pointed at the new root.
                var newMetadata = await GetCachedMetadata(index, modlist, Source, df, _dat);

                newMetadata.Root = Destination.Info.ToFullRoot();
                ItemMetadata originalDestinationMetadata = null;
                try
                {
                    originalDestinationMetadata = await GetCachedMetadata(index, modlist, Destination, df, _dat);
                } catch
                {
                    originalDestinationMetadata = new ItemMetadata(Destination);
                }

                // Set 0 needs special handling.
                if (Source.Info.PrimaryType == XivItemType.equipment && Source.Info.PrimaryId == 0)
                {
                    var set1Root     = new XivDependencyRoot(Source.Info.PrimaryType, 1, null, null, Source.Info.Slot);
                    var set1Metadata = await GetCachedMetadata(index, modlist, set1Root, df, _dat);

                    newMetadata.EqpEntry = set1Metadata.EqpEntry;

                    if (Source.Info.Slot == "met")
                    {
                        newMetadata.GmpEntry = set1Metadata.GmpEntry;
                    }
                }
                else if (Destination.Info.PrimaryType == XivItemType.equipment && Destination.Info.PrimaryId == 0)
                {
                    newMetadata.EqpEntry = null;
                    newMetadata.GmpEntry = null;
                }


                // Now figure out the path names for all of our new paths.
                // These dictionarys map Old Path => New Path
                Dictionary <string, string> newModelPaths        = new Dictionary <string, string>();
                Dictionary <string, string> newMaterialPaths     = new Dictionary <string, string>();
                Dictionary <string, string> newMaterialFileNames = new Dictionary <string, string>();
                Dictionary <string, string> newTexturePaths      = new Dictionary <string, string>();
                Dictionary <string, string> newAvfxPaths         = new Dictionary <string, string>();

                if (ProgressReporter != null)
                {
                    ProgressReporter.Report("Calculating files to copy...");
                }

                // For each path, replace any instances of our primary and secondary types.
                foreach (var path in originalModelPaths)
                {
                    newModelPaths.Add(path, UpdatePath(Source, Destination, path));
                }

                foreach (var path in originalMaterialPaths)
                {
                    var nPath = UpdatePath(Source, Destination, path);
                    newMaterialPaths.Add(path, nPath);
                    var fName = Path.GetFileName(path);

                    if (!newMaterialFileNames.ContainsKey(fName))
                    {
                        newMaterialFileNames.Add(fName, Path.GetFileName(nPath));
                    }
                }

                foreach (var path in originalTexturePaths)
                {
                    newTexturePaths.Add(path, UpdatePath(Source, Destination, path));
                }

                foreach (var path in originalVfxPaths)
                {
                    newAvfxPaths.Add(path, UpdatePath(Source, Destination, path));
                }

                var destItem = Destination.GetFirstItem();
                var srcItem  = (await Source.GetAllItems(singleVariant))[0];
                var iCat     = destItem.SecondaryCategory;
                var iName    = destItem.Name;


                var files = newModelPaths.Select(x => x.Value).Union(
                    newMaterialPaths.Select(x => x.Value)).Union(
                    newAvfxPaths.Select(x => x.Value)).Union(
                    newTexturePaths.Select(x => x.Value));
                var allFiles = new HashSet <string>();
                foreach (var f in files)
                {
                    allFiles.Add(f);
                }

                allFiles.Add(Destination.Info.GetRootFile());

                if (ProgressReporter != null)
                {
                    ProgressReporter.Report("Getting modlist...");
                }

                if (ProgressReporter != null)
                {
                    ProgressReporter.Report("Removing existing modifications to destination root...");
                }

                if (Destination != Source)
                {
                    var dPath   = Destination.Info.GetRootFolder();
                    var allMods = modlist.Mods.ToList();
                    foreach (var mod in allMods)
                    {
                        if (mod.fullPath.StartsWith(dPath) && !mod.IsInternal())
                        {
                            if (Destination.Info.SecondaryType != null || Destination.Info.Slot == null)
                            {
                                // If this is a slotless root, purge everything.
                                await _modding.DeleteMod(mod.fullPath, false, index, modlist);
                            }
                            else if (allFiles.Contains(mod.fullPath) || mod.fullPath.Contains(Destination.Info.GetBaseFileName(true)))
                            {
                                // Otherwise, only purge the files we're replacing, and anything else that
                                // contains our slot name.
                                await _modding.DeleteMod(mod.fullPath, false, index, modlist);
                            }
                        }
                    }
                }

                if (ProgressReporter != null)
                {
                    ProgressReporter.Report("Copying models...");
                }

                // Load, Edit, and resave the model files.
                foreach (var kv in newModelPaths)
                {
                    var src    = kv.Key;
                    var dst    = kv.Value;
                    var offset = index.Get8xDataOffset(src);
                    var xmdl   = await _mdl.GetRawMdlData(src, false, offset);

                    var tmdl = TTModel.FromRaw(xmdl);

                    if (xmdl == null || tmdl == null)
                    {
                        continue;
                    }

                    tmdl.Source  = dst;
                    xmdl.MdlPath = dst;

                    // Replace any material references as needed.
                    foreach (var m in tmdl.MeshGroups)
                    {
                        foreach (var matKv in newMaterialFileNames)
                        {
                            m.Material = m.Material.Replace(matKv.Key, matKv.Value);
                        }
                    }

                    // Save new Model.
                    var bytes = await _mdl.MakeNewMdlFile(tmdl, xmdl, null);

                    await _dat.WriteModFile(bytes, dst, ApplicationSource, destItem, index, modlist);
                }

                if (ProgressReporter != null)
                {
                    ProgressReporter.Report("Copying textures...");
                }

                // Raw Copy all Texture files to the new destinations to avoid having the MTRL save functions auto-generate blank textures.
                foreach (var kv in newTexturePaths)
                {
                    var src = kv.Key;
                    var dst = kv.Value;

                    await _dat.CopyFile(src, dst, ApplicationSource, true, destItem, index, modlist);
                }


                if (ProgressReporter != null)
                {
                    ProgressReporter.Report("Copying materials...");
                }
                HashSet <string> CopiedMaterials = new HashSet <string>();
                // Load every Material file and edit the texture references to the new texture paths.
                foreach (var kv in newMaterialPaths)
                {
                    var src = kv.Key;
                    var dst = kv.Value;
                    try
                    {
                        var offset = index.Get8xDataOffset(src);
                        if (offset == 0)
                        {
                            continue;
                        }
                        var xivMtrl = await _mtrl.GetMtrlData(offset, src, 11);

                        xivMtrl.MTRLPath = dst;

                        for (int i = 0; i < xivMtrl.TexturePathList.Count; i++)
                        {
                            foreach (var tkv in newTexturePaths)
                            {
                                xivMtrl.TexturePathList[i] = xivMtrl.TexturePathList[i].Replace(tkv.Key, tkv.Value);
                            }
                        }

                        await _mtrl.ImportMtrl(xivMtrl, destItem, ApplicationSource, index, modlist);

                        CopiedMaterials.Add(dst);
                    }
                    catch (Exception ex)
                    {
                        // Let functions later handle this mtrl then.
                    }
                }

                if (ProgressReporter != null)
                {
                    ProgressReporter.Report("Copying VFX...");
                }
                // Copy VFX files.
                foreach (var kv in newAvfxPaths)
                {
                    var src = kv.Key;
                    var dst = kv.Value;

                    await _dat.CopyFile(src, dst, ApplicationSource, true, destItem, index, modlist);
                }

                if (ProgressReporter != null)
                {
                    ProgressReporter.Report("Creating missing variants...");
                }
                // Check to see if we need to add any variants
                var cloneNum = newMetadata.ImcEntries.Count >= 2 ? 1 : 0;
                while (originalDestinationMetadata.ImcEntries.Count > newMetadata.ImcEntries.Count)
                {
                    // Clone Variant 1 into the variants we are missing.
                    newMetadata.ImcEntries.Add((XivImc)newMetadata.ImcEntries[cloneNum].Clone());
                }


                if (singleVariant >= 0)
                {
                    if (ProgressReporter != null)
                    {
                        ProgressReporter.Report("Setting single-variant data...");
                    }

                    if (singleVariant < newMetadata.ImcEntries.Count)
                    {
                        var v = newMetadata.ImcEntries[singleVariant];

                        for (int i = 0; i < newMetadata.ImcEntries.Count; i++)
                        {
                            newMetadata.ImcEntries[i] = (XivImc)v.Clone();
                        }
                    }
                }

                // Update Skeleton references to be for the correct set Id.
                var setId = Destination.Info.SecondaryId == null ? (ushort)Destination.Info.PrimaryId : (ushort)Destination.Info.SecondaryId;
                foreach (var entry in newMetadata.EstEntries)
                {
                    entry.Value.SetId = setId;
                }

                if (ProgressReporter != null)
                {
                    ProgressReporter.Report("Copying metdata...");
                }

                // Poke through the variants and adjust any that point to null Material Sets to instead use a valid one.
                if (newMetadata.ImcEntries.Count > 0 && originalMetadata.ImcEntries.Count > 0)
                {
                    var valid = newMetadata.ImcEntries.FirstOrDefault(x => x.MaterialSet != 0).MaterialSet;
                    if (valid <= 0)
                    {
                        valid = originalMetadata.ImcEntries.FirstOrDefault(x => x.MaterialSet != 0).MaterialSet;
                    }

                    for (int i = 0; i < newMetadata.ImcEntries.Count; i++)
                    {
                        var entry = newMetadata.ImcEntries[i];
                        if (entry.MaterialSet == 0)
                        {
                            entry.MaterialSet = valid;
                        }
                    }
                }

                await ItemMetadata.SaveMetadata(newMetadata, ApplicationSource, index, modlist);

                // Save the new Metadata file via the batch function so that it's only written to the memory cache for now.
                await ItemMetadata.ApplyMetadataBatched(new List <ItemMetadata>() { newMetadata }, index, modlist, false);



                if (ProgressReporter != null)
                {
                    ProgressReporter.Report("Filling in missing material sets...");
                }
                // Validate all variants/material sets for valid materials, and copy materials as needed to fix.
                if (Imc.UsesImc(Destination))
                {
                    var mSets = newMetadata.ImcEntries.Select(x => x.MaterialSet).Distinct();
                    foreach (var mSetId in mSets)
                    {
                        var path = Destination.Info.GetRootFolder() + "material/v" + mSetId.ToString().PadLeft(4, '0') + "/";
                        foreach (var mkv in newMaterialFileNames)
                        {
                            // See if the material was copied over.
                            var destPath = path + mkv.Value;
                            if (CopiedMaterials.Contains(destPath))
                            {
                                continue;
                            }

                            string existentCopy = null;

                            // If not, find a material where one *was* copied over.
                            foreach (var mSetId2 in mSets)
                            {
                                var p2 = Destination.Info.GetRootFolder() + "material/v" + mSetId2.ToString().PadLeft(4, '0') + "/";
                                foreach (var cmat2 in CopiedMaterials)
                                {
                                    if (cmat2 == p2 + mkv.Value)
                                    {
                                        existentCopy = cmat2;
                                        break;
                                    }
                                }
                            }

                            // Shouldn't ever actually hit this, but if we do, nothing to be done about it.
                            if (existentCopy == null)
                            {
                                continue;
                            }

                            // Copy the material over.
                            await _dat.CopyFile(existentCopy, destPath, ApplicationSource, true, destItem, index, modlist);
                        }
                    }
                }

                if (ProgressReporter != null)
                {
                    ProgressReporter.Report("Updating modlist...");
                }

                if (modPack == null)
                {
                    modPack = new ModPack()
                    {
                        author = "System", name = "Item Copy - " + srcItem.Name + " to " + iName, url = "", version = "1.0"
                    };
                }

                List <Mod> mods = new List <Mod>();
                foreach (var mod in modlist.Mods)
                {
                    if (allFiles.Contains(mod.fullPath))
                    {
                        // Ensure all of our modified files are attributed correctly.
                        mod.name     = iName;
                        mod.category = iCat;
                        mod.source   = ApplicationSource;
                        mod.modPack  = modPack;

                        mods.Add(mod);
                    }
                }

                if (!modlist.ModPacks.Any(x => x.name == modPack.name))
                {
                    modlist.ModPacks.Add(modPack);
                }

                if (doSave)
                {
                    // Save everything.
                    await _index.SaveIndexFile(index);

                    await _modding.SaveModListAsync(modlist);
                }

                XivCache.QueueDependencyUpdate(allFiles.ToList());

                if (saveDirectory != null)
                {
                    ProgressReporter.Report("Creating TTMP File...");
                    var desc = "Item Converter Modpack - " + srcItem.Name + " -> " + iName + "\nCreated at: " + DateTime.Now.ToString();
                    // Time to save the modlist to file.
                    var dir   = new DirectoryInfo(saveDirectory);
                    var _ttmp = new TTMP(dir, ApplicationSource);
                    var smpd  = new SimpleModPackData()
                    {
                        Author            = modPack.author,
                        Description       = desc,
                        Url               = modPack.url,
                        Version           = new Version(1, 0, 0),
                        Name              = modPack.name,
                        SimpleModDataList = new List <SimpleModData>()
                    };

                    foreach (var mod in mods)
                    {
                        var size = await _dat.GetCompressedFileSize(mod.data.modOffset, df);

                        var smd = new SimpleModData()
                        {
                            Name      = iName,
                            FullPath  = mod.fullPath,
                            DatFile   = df.GetDataFileName(),
                            Category  = iCat,
                            IsDefault = false,
                            ModSize   = size,
                            ModOffset = mod.data.modOffset
                        };
                        smpd.SimpleModDataList.Add(smd);
                    }

                    await _ttmp.CreateSimpleModPack(smpd, XivCache.GameInfo.GameDirectory, null, true);
                }



                if (ProgressReporter != null)
                {
                    ProgressReporter.Report("Root copy complete.");
                }

                // Return the final file conversion listing.
                var ret  = newModelPaths.Union(newMaterialPaths).Union(newAvfxPaths).Union(newTexturePaths);
                var dict = ret.ToDictionary(x => x.Key, x => x.Value);
                dict.Add(Source.Info.GetRootFile(), Destination.Info.GetRootFile());
                return(dict);
            } finally
            {
                XivCache.CacheWorkerEnabled = workerStatus;
            }
        }
Пример #23
0
 public virtual OperationResult UpdateEntity(Mdl mdl, bool isSave = true)
 {
     return(mdlRepository.Update(mdl, isSave));
 }
Пример #24
0
        static void BatchExportItem(string path, IItemModel item, XivModelInfo secondaryModelInfo, Func <IEnumerable <XivRace> > getRaces)
        {
            if (File.Exists(path))
            {
                return;
            }

            WriteLine($"Exporting {item.GetType().Name} {item.Name}: {Path.GetFileNameWithoutExtension(path)}");

            var items = new List <IItemModel>();

            var metadata = new ExportMetadata();

            metadata.Name = item.Name;

            var mdl   = new Mdl(_gameDir, item.DataFile);
            var races = getRaces();

            items.Add(item);

            if (item.ModelInfo is XivMonsterModelInfo)
            {
                var info = item.ModelInfo as XivMonsterModelInfo;
                if (info.ModelType.Equals(XivItemType.demihuman) && item is XivMount)
                {
                    items.Clear();
                    var met = item.Clone() as XivMount;
                    met.TertiaryCategory = "Head";
                    var top = item.Clone() as XivMount;
                    top.TertiaryCategory = "Body";
                    var glv = item.Clone() as XivMount;
                    glv.TertiaryCategory = "Hand";
                    var dwn = item.Clone() as XivMount;
                    dwn.TertiaryCategory = "Leg";
                    var sho = item.Clone() as XivMount;
                    sho.TertiaryCategory = "Feet";

                    items.Add(met);
                    items.Add(top);
                    items.Add(glv);
                    items.Add(dwn);
                    items.Add(sho);
                }
            }

            foreach (var race in races)
            {
                var mdlDatas    = new List <XivMdl>();
                var textureSets = new List <Dictionary <string, ModelTextureData> >();

                foreach (var iItem in items)
                {
                    try
                    {
                        var mdlData = mdl.GetRawMdlData(iItem, race).Result;
                        if (mdlData != null)
                        {
                            mdlDatas.Add(mdlData);

                            textureSets.Add(TexTools.MaterialsHelper.GetMaterials(_gameDir, item, mdlData, race).Result);

                            continue;
                        }
                    }
                    catch
                    { }
                    WriteLine($"Failed to get {iItem.Name}。 Got null.");
                    if (items.Count > 1)
                    {
                        WriteLine($"{iItem.Name} has no components like {iItem.TertiaryCategory}.");
                    }
                }

                try
                {
                    var set = BatchExportSets(mdlDatas, textureSets);
                    set.Name = TexTools.XivStringRaces.ToRaceGenderName(race);
                    metadata.Sets.Add(set);
                }
                catch (NotImplementedException e)
                { }
            }
            if (metadata.Sets[0].Models.Count == 0)
            {
                WriteLine($"Empty model {item.Name}.");
                return;
            }

            var metadataJson = JsonConvert.SerializeObject(metadata);

            File.WriteAllText(path, metadataJson);

            WriteLine($"Exported {item.GetType().Name} {item.Name}: {Path.GetFileNameWithoutExtension(path)}");
        }
Пример #25
0
        public async Task AsyncInit()
        {
            var root = _item.GetRoot();

            if (root == null)
            {
                return;
            }

            var gd   = XivCache.GameInfo.GameDirectory;
            var lang = XivCache.GameInfo.GameLanguage;
            var df   = IOUtil.GetDataFileFromPath(root.Info.GetRootFile());

            var _index    = new Index(gd);
            var _mtrl     = new Mtrl(XivCache.GameInfo.GameDirectory);
            var _mdl      = new Mdl(gd, df);
            var _imc      = new Imc(gd);
            var raceRegex = new Regex("c([0-9]{4})[^b]");

            ItemNameBox.Text = _item.Name;

            var setName = root.Info.GetBaseFileName(false);

            SetLabel.Text = "Set: " + setName;

            if (!String.IsNullOrWhiteSpace(root.Info.Slot))
            {
                var niceSlot = Mdl.SlotAbbreviationDictionary.FirstOrDefault(x => x.Value == root.Info.Slot);
                if (niceSlot.Key != null)
                {
                    SlotLabel.Text = "Slot: " + niceSlot.Key + " (" + root.Info.Slot + ")";
                }
                else
                {
                    SlotLabel.Text = "Slot: Unknown (" + root.Info.Slot + ")";
                }
            }
            else
            {
                SlotLabel.Text = "Slot: --";
            }

            var usesImc = Imc.UsesImc(_item);

            if (usesImc)
            {
                VariantLabel.Text = "Variant: " + _item.ModelInfo.ImcSubsetID;
            }
            else
            {
                VariantLabel.Text = "Variant: --";
            }

            var mSet = await _imc.GetMaterialSetId(_item);

            if (mSet > 0)
            {
                MaterialSetLabel.Text = "Material Set: " + mSet;
            }
            else
            {
                MaterialSetLabel.Text = "Material Set: --";
            }

            var races = XivRaces.PlayableRaces;

            var models = await root.GetModelFiles();

            var materials = await root.GetMaterialFiles(mSet);

            #region Race Chart
            var rowIdx = 1;
            foreach (var race in races)
            {
                var rCode = race.GetRaceCode();

                var row = new RowDefinition();
                row.Height = new GridLength(30);
                RacialGrid.RowDefinitions.Add(row);

                var lBase = new Label();
                lBase.Content = race.GetDisplayName();
                lBase.SetValue(Grid.RowProperty, rowIdx);

                RacialGrid.Children.Add(lBase);

                XivRace?usedMdlRace = race;

                string usedMdl = null;;
                if (race != XivRace.All_Races)
                {
                    // Check if the race has a model.
                    var mdl = models.FirstOrDefault(x => x.Contains("c" + rCode));
                    if (mdl == null)
                    {
                        // Gotta see which race they're shared from.
                        var node   = XivRaceTree.GetNode(race);
                        var parent = node.Parent;

                        while (parent != null)
                        {
                            var code = parent.Race.GetRaceCode();
                            mdl = models.FirstOrDefault(x => x.Contains("c" + code));
                            if (mdl != null)
                            {
                                usedMdlRace = parent.Race;
                                usedMdl     = mdl;
                                break;
                            }
                            parent = parent.Parent;
                        }

                        if (mdl == null)
                        {
                            // No model exists for this item.
                            usedMdlRace = null;
                        }
                    }
                    else
                    {
                        usedMdl = mdl;
                    }
                }

                var mdlRaceString = "None";
                if (usedMdlRace == race)
                {
                    mdlRaceString = "Own";
                }
                else
                {
                    if (usedMdlRace != null)
                    {
                        mdlRaceString = ((XivRace)usedMdlRace).GetDisplayName();
                    }
                }

                XivRace?usedMtrlRace = usedMdlRace;
                if (race != XivRace.All_Races)
                {
                    if (usedMdlRace == null)
                    {
                        usedMtrlRace = null;
                    }
                    else
                    {
                        // Get the materials used by this racial's model.
                        var mdl          = usedMdl;
                        var mdlMaterials = await XivCache.GetChildFiles(mdl);

                        var mtrl = mdlMaterials.FirstOrDefault(x => raceRegex.IsMatch(x));

                        if (mtrl == null)
                        {
                            usedMtrlRace = null;
                        }
                        else
                        {
                            var code = raceRegex.Match(mtrl).Groups[1].Value;
                            usedMtrlRace = XivRaces.GetXivRace(code);
                            if (usedMtrlRace == XivRace.All_Races)
                            {
                                usedMtrlRace = null;
                            }
                        }
                    }
                }

                var mtrlRaceString = "None";
                if (usedMtrlRace == race)
                {
                    mtrlRaceString = "Own";
                }
                else
                {
                    if (usedMtrlRace != null)
                    {
                        mtrlRaceString = ((XivRace)usedMtrlRace).GetDisplayName();
                    }
                }

                var lMdl = new Label();
                lMdl.Content = mdlRaceString;
                lMdl.SetValue(Grid.RowProperty, rowIdx);
                lMdl.SetValue(Grid.ColumnProperty, 1);
                RacialGrid.Children.Add(lMdl);

                var lMtrl = new Label();
                lMtrl.Content = mtrlRaceString;
                lMtrl.SetValue(Grid.RowProperty, rowIdx);
                lMtrl.SetValue(Grid.ColumnProperty, 2);
                RacialGrid.Children.Add(lMtrl);


                rowIdx++;
            }
            #endregion


            if (Imc.UsesImc(_item) && _item.ModelInfo != null)
            {
                var myImcSubsetId = _item.ModelInfo.ImcSubsetID;
                var allItems      = await root.GetAllItems();

                var fInfo = await _imc.GetFullImcInfo(_item);

                var entries = fInfo.GetAllEntries(_item.GetItemSlotAbbreviation(), true);

                foreach (var item in allItems)
                {
                    SameModelItems.Add(new KeyValuePair <string, IItem>(item.Name, item));
                    if (entries.Count > item.ModelInfo.ImcSubsetID)
                    {
                        var imSet = entries[item.ModelInfo.ImcSubsetID].MaterialSet;

                        if (mSet == imSet)
                        {
                            SameMSetItems.Add(new KeyValuePair <string, IItem>(item.Name, item));
                        }
                    }
                    if (item.ModelInfo.ImcSubsetID == myImcSubsetId)
                    {
                        SameVariantItems.Add(new KeyValuePair <string, IItem>(item.Name, item));
                    }
                }
            }
        }
Пример #26
0
        public ImportModelViewModel(ImportModelView view, IItemModel item, XivRace race, string submeshId, bool dataOnly, Action onComplete = null)
        {
            _view       = view;
            _item       = item;
            _race       = race;
            _submeshId  = submeshId;
            _dataOnly   = dataOnly;
            _onComplete = onComplete;

            var gameDirectory = new DirectoryInfo(Settings.Default.FFXIV_Directory);
            var saveDirectory = new DirectoryInfo(Settings.Default.Save_Directory);
            var dataFile      = IOUtil.GetDataFileFromPath(_item.GetItemRootFolder());

            _mdl       = new Mdl(gameDirectory, dataFile);
            _importers = _mdl.GetAvailableImporters();


            // We need to explicitly fork this onto a new thread to avoid deadlock.
            Task.Run(AssignPath).Wait();

            var defaultPath = $"{IOUtil.MakeItemSavePath(_item, saveDirectory, _race)}\\3D";

            defaultPath = defaultPath.Replace("/", "\\");
            var modelName = Path.GetFileNameWithoutExtension(_internalPath);


            // Scan to see which file type(s) actually exist.
            bool foundValidFile = false;

            // FBX is default, so check that first.
            var startingPath = Path.Combine(defaultPath, modelName) + ".fbx";

            if (File.Exists(startingPath))
            {
                foundValidFile = true;
            }
            if (!foundValidFile)
            {
                foreach (var suffix in _importers)
                {
                    startingPath = Path.Combine(defaultPath, modelName) + "." + suffix;
                    if (File.Exists(startingPath))
                    {
                        foundValidFile = true;
                        break;
                    }
                }
            }

            if (!foundValidFile)
            {
                startingPath = "";
            }


            _view.FileNameTextBox.Text = startingPath;

            // Event Handlers
            _view.SelectFileButton.Click += SelectFileButton_Click;
            _view.ImportButton.Click     += ImportButton_Click;
            _view.EditButton.Click       += EditButton_Click;
            _view.Closing += _view_Closing;

            // Default Settings for specific categories.
            if (item.SecondaryCategory == XivStrings.Face)
            {
                _view.EnableShapeDataButton.IsChecked = true;
            }
            if (item.SecondaryCategory == XivStrings.Hair)
            {
                _view.CloneUV1Button.IsChecked = true;
            }

            var iType = item.GetPrimaryItemType();

            if (iType == xivModdingFramework.Items.Enums.XivItemType.equipment || iType == xivModdingFramework.Items.Enums.XivItemType.accessory || iType == xivModdingFramework.Items.Enums.XivItemType.weapon)
            {
                _view.ForceUVsButton.IsChecked = true;
            }
        }