/// <summary> /// Creates a new ItemMetaData entry from the constituent files around the FFXIV file system. /// </summary> /// <param name="root"></param> /// <returns></returns> private static async Task <ItemMetadata> CreateFromRaw(XivDependencyRoot root, bool forceDefault = false) { var _eqp = new Eqp(XivCache.GameInfo.GameDirectory); var _imc = new Imc(XivCache.GameInfo.GameDirectory); // These functions generate the path::offset to each of our // contiguous metadata entries. var imcPaths = await root.GetImcEntryPaths(); var ret = new ItemMetadata(root); if (imcPaths.Count > 0) { ret.ImcEntries = await _imc.GetEntries(imcPaths, forceDefault); } ret.EqpEntry = await _eqp.GetEqpEntry(root.Info, forceDefault); ret.EqdpEntries = await _eqp.GetEquipmentDeformationParameters(root.Info, forceDefault); ret.EstEntries = await Est.GetExtraSkeletonEntries(root, forceDefault); ret.GmpEntry = await _eqp.GetGimmickParameter(root, forceDefault); return(ret); }
public async Task <List <IItemModel> > GetSameVariantList(IItemModel item) { var sameModelItems = new List <IItemModel>(); if (!item.PrimaryCategory.Equals(XivStrings.Gear)) { sameModelItems.Add((IItemModel)item.Clone()); return(sameModelItems); } sameModelItems = await GetSameModelList(item); var imc = new Imc(_gameDirectory, XivDataFile._04_Chara); var originalInfo = await imc.GetImcInfo(item); var sameMaterialItems = new List <IItemModel>(); foreach (var i in sameModelItems) { var info = await imc.GetImcInfo(i); if (info.Variant == originalInfo.Variant) { sameMaterialItems.Add(i); } } return(sameMaterialItems); }
public Imc Post(Imc values) { Imc imcCalc = values; imcCalc.ImcValue = imcCalc.Weight / (imcCalc.Height * imcCalc.Height); return(imcCalc); }
public async Task <Dictionary <string, char[]> > GetDemiHumanMountTextureEquipPartList(IItemModel itemModel) { var parts = new[] { 'a', 'b', 'c', 'd', 'e', 'f' }; var equipPartDictionary = new Dictionary <string, char[]>(); var index = new Index(_gameDirectory); var imc = new Imc(_gameDirectory, XivDataFile._04_Chara); var version = (await imc.GetImcInfo(itemModel, itemModel.ModelInfo)).Version.ToString().PadLeft(4, '0'); var id = itemModel.ModelInfo.ModelID.ToString().PadLeft(4, '0'); var bodyVer = itemModel.ModelInfo.Body.ToString().PadLeft(4, '0'); var mtrlFolder = $"chara/demihuman/d{id}/obj/equipment/e{bodyVer}/material/v{version}"; var files = await index.GetAllHashedFilesInFolder(HashGenerator.GetHash(mtrlFolder), XivDataFile._04_Chara); foreach (var slotAbr in SlotAbbreviationDictionary) { var charList = (from part in parts let mtrlFile = $"mt_d{id}e{bodyVer}_{slotAbr.Value}_{part}.mtrl" where files.Contains(HashGenerator.GetHash(mtrlFile)) select part).ToList(); if (charList.Count > 0) { equipPartDictionary.Add(slotAbr.Key, charList.ToArray()); } } return(equipPartDictionary); }
private async Task LoadItems() { List <string> children = new List <string>(); var root = _item.GetRoot(); if (root != null) { if (_level == XivDependencyLevel.Model) { children = await root.GetModelFiles(); } else if (_level == XivDependencyLevel.Material) { var imc = new Imc(XivCache.GameInfo.GameDirectory); try { var entry = await imc.GetImcInfo((IItemModel)_item); children = await root.GetMaterialFiles(entry.Variant); } catch { children = await root.GetMaterialFiles(0); } } else if (_level == XivDependencyLevel.Texture) { try { var imc = new Imc(XivCache.GameInfo.GameDirectory); var entry = await imc.GetImcInfo((IItemModel)_item); children = await root.GetTextureFiles(entry.Variant); } catch { children = await root.GetTextureFiles(0); } } else { // Invalid or root, nothing listed. } } var index = new Index(XivCache.GameInfo.GameDirectory); foreach (var file in children) { var exists = await index.FileExists(file); if (!exists) { continue; } Files.Add(new FileEntry(file)); } }
public Imc CalcIMC(double weight, double height, string name) { var result = GetImc(weight, height); Imc objectImc = new Imc() { ImcValue = result, Text = $"{name}, your IMC is: {result}" }; return(objectImc); }
/// <summary> /// Gets the avfx path /// </summary> /// <param name="itemModel">The item to get the avfx path for</param> /// <param name="itemType">The type of the item</param> /// <returns>A tuple containing the path folder and file</returns> public static async Task <(string Folder, string File)> GetVfxPath(IItemModel itemModel) { // get the vfx version from the imc file var imc = new Imc(XivCache.GameInfo.GameDirectory); var imcInfo = await imc.GetImcInfo(itemModel); int vfx = imcInfo.Vfx; var root = itemModel.GetRootInfo(); return(await GetVfxPath(root, vfx)); }
public SituationImcNameHelper(double imc) { Resposta = imc switch { (< 18.5) => Imc.AbaixoDoPeso, (< 25) => Imc.PesoNormal, (< 30) => Imc.Sobrepeso, (< 35) => Imc.ObesidadeGrau1, (< 40) => Imc.ObesidadeGrau2, _ => Imc.ObesidadeGrau3 }; }
/// <summary> /// Deserializes the binary IMC data into a list of IMC entries. /// </summary> /// <param name="data"></param> /// <returns></returns> private static List <XivImc> DeserializeImcData(byte[] data, XivDependencyRoot root, uint dataVersion) { const int ImcSubEntrySize = 6; var entries = data.Length / ImcSubEntrySize; List <XivImc> ret = new List <XivImc>(); for (int i = 0; i < entries; i++) { var entryData = data.Skip(i * ImcSubEntrySize).Take(ImcSubEntrySize).ToArray(); ret.Add(Imc.DeserializeEntry(entryData)); } return(ret); }
public async Task ShowConversionStats() { if (!DestinationOk(Destination)) { return; } var imc = new Imc(XivCache.GameInfo.GameDirectory); SourceBox.Text = Source.Info.GetBaseFileName() + " (" + SourceItem.Name + ")"; DestinationBox.Text = Destination.Info.GetBaseFileName() + " (" + DestinationItem.Name + ")"; if (Imc.UsesImc(Source)) { try { var sourceInfo = await imc.GetFullImcInfo(Source.GetRawImcFilePath()); var destInfo = await imc.GetFullImcInfo(Destination.GetRawImcFilePath()); SourceVariantsBox.Text = (sourceInfo.SubsetCount + 1).ToString(); DestinationVariantsBox.Text = (destInfo.SubsetCount + 1).ToString(); SameVariantBox.IsEnabled = true; SameVariantBox.IsChecked = true; } catch { SameVariantBox.IsEnabled = true; SameVariantBox.IsChecked = true; } } else { SameVariantBox.IsEnabled = false; SameVariantBox.IsChecked = false; SourceVariantsBox.Text = "1"; DestinationVariantsBox.Text = "1"; } var items = await Destination.GetAllItems(); AffectedItemsBox.Items.Clear(); foreach (var item in items) { AffectedItemsBox.Items.Add(item.Name); } }
/// <summary> /// Serializes the IMC data entries for the given meta file. /// </summary> /// <param name="meta"></param> /// <returns></returns> private static byte[] SerializeImcData(ItemMetadata meta) { // IMC Serialization is pretty straight forward, it's just // write the binary data from the IMC entries in sequence. // IMC entries are a static 6 bytes long, and ordered in simple // straight consecutive order, so our index order matches subeset ID. List <byte> bytes = new List <byte>(); foreach (var entry in meta.ImcEntries) { bytes.AddRange(Imc.SerializeEntry(entry)); } return(bytes.ToArray()); }
/// <summary> /// Gets the avfx path /// </summary> /// <param name="itemModel">The item to get the avfx path for</param> /// <param name="itemType">The type of the item</param> /// <returns>A tuple containing the path folder and file</returns> private async Task <(string Folder, string File)> GetVfxPath(IItemModel itemModel, XivItemType itemType) { // get the vfx version from the imc file var imc = new Imc(_modding, _dataFile); var imcInfo = await imc.GetImcInfo(itemModel, itemModel.ModelInfo); int vfx = imcInfo.Vfx; var id = itemModel.ModelInfo.ModelID.ToString().PadLeft(4, '0'); var bodyVer = itemModel.ModelInfo.Body.ToString().PadLeft(4, '0'); string vfxFolder, vfxFile; switch (itemType) { case XivItemType.equipment: vfxFolder = $"chara/{itemType}/e{id}/vfx/eff"; vfxFile = $"ve{vfx.ToString().PadLeft(4, '0')}.avfx"; break; case XivItemType.weapon: vfxFolder = $"chara/{itemType}/w{id}/obj/body/b{bodyVer}/vfx/eff"; vfxFile = $"vw{vfx.ToString().PadLeft(4, '0')}.avfx"; break; case XivItemType.monster: vfxFolder = $"chara/{itemType}/m{id}/obj/body/b{bodyVer}/vfx/eff"; vfxFile = $"vm{vfx.ToString().PadLeft(4, '0')}.avfx"; break; case XivItemType.demihuman: vfxFolder = $"chara/{itemType}/d{id}/obj/equipment/e{bodyVer}/vfx/eff"; vfxFile = $"ve{vfx.ToString().PadLeft(4, '0')}.avfx"; break; default: vfxFolder = ""; vfxFile = ""; break; } return(vfxFolder, vfxFile); }
/// <summary> /// Gets the mtrl path for a given item /// </summary> /// <param name="itemModel">Item that contains model data</param> /// <param name="xivRace">The race for the requested data</param> /// <param name="part">The mtrl part <see cref="GearInfo.GetPartList(IItemModel, XivRace)"/></param> /// <param name="itemType">The type of the item</param> /// <returns>A tuple containing the mtrl folder and file, and whether it has a vfx</returns> private (string Folder, string File, bool HasVfx) GetMtrlPath(IItemModel itemModel, XivRace xivRace, char part, XivItemType itemType) { // The default version number var version = "0001"; var hasVfx = false; if (itemType != XivItemType.human && itemType != XivItemType.furniture) { // get the items version from the imc file var imc = new Imc(_gameDirectory, _dataFile); var imcInfo = imc.GetImcInfo(itemModel, itemModel.ModelInfo); version = imcInfo.Version.ToString().PadLeft(4, '0'); if (imcInfo.Vfx > 0) { hasVfx = true; } } var id = itemModel.ModelInfo.ModelID.ToString().PadLeft(4, '0'); var bodyVer = itemModel.ModelInfo.Body.ToString().PadLeft(4, '0'); var race = xivRace.GetRaceCode(); string mtrlFolder = "", mtrlFile = ""; switch (itemType) { case XivItemType.equipment: mtrlFolder = $"chara/{itemType}/e{id}/material/v{version}"; mtrlFile = $"mt_c{race}e{id}_{SlotAbbreviationDictionary[itemModel.ItemCategory]}_{part}{MtrlExtension}"; break; case XivItemType.accessory: mtrlFolder = $"chara/{itemType}/a{id}/material/v{version}"; mtrlFile = $"mt_c{race}a{id}_{SlotAbbreviationDictionary[itemModel.ItemCategory]}_{part}{MtrlExtension}"; break; case XivItemType.weapon: mtrlFolder = $"chara/{itemType}/w{id}/obj/body/b{bodyVer}/material/v{version}"; mtrlFile = $"mt_w{id}b{bodyVer}_{part}{MtrlExtension}"; break; case XivItemType.monster: mtrlFolder = $"chara/{itemType}/m{id}/obj/body/b{bodyVer}/material/v{version}"; mtrlFile = $"mt_m{id}b{bodyVer}_{part}{MtrlExtension}"; break; case XivItemType.demihuman: mtrlFolder = $"chara/{itemType}/d{id}/obj/equipment/e{bodyVer}/material/v{version}"; mtrlFile = $"mt_d{id}e{bodyVer}_{SlotAbbreviationDictionary[itemModel.ItemSubCategory]}_{part}{MtrlExtension}"; break; case XivItemType.human: if (itemModel.ItemCategory.Equals(XivStrings.Body)) { mtrlFolder = $"chara/{itemType}/c{race}/obj/body/b{bodyVer}/material"; mtrlFile = $"mt_c{race}b{bodyVer}_{part}{MtrlExtension}"; } else if (itemModel.ItemCategory.Equals(XivStrings.Hair)) { // Hair has a version number, but no IMC, so we leave it at the default 0001 mtrlFolder = $"chara/{itemType}/c{race}/obj/hair/h{bodyVer}/material/v{version}"; mtrlFile = $"mt_c{race}h{bodyVer}_{SlotAbbreviationDictionary[itemModel.ItemSubCategory]}_{part}{MtrlExtension}"; } else if (itemModel.ItemCategory.Equals(XivStrings.Face)) { mtrlFolder = $"chara/{itemType}/c{race}/obj/face/f{bodyVer}/material"; mtrlFile = $"mt_c{race}f{bodyVer}_{SlotAbbreviationDictionary[itemModel.ItemSubCategory]}_{part}{MtrlExtension}"; } else if (itemModel.ItemCategory.Equals(XivStrings.Tail)) { mtrlFolder = $"chara/{itemType}/c{race}/obj/tail/t{bodyVer}/material"; mtrlFile = $"mt_c{race}t{bodyVer}_{part}{MtrlExtension}"; } break; case XivItemType.furniture: if (itemModel.ItemCategory.Equals(XivStrings.Furniture_Indoor)) { mtrlFolder = $"bgcommon/hou/indoor/general/{id}/material"; mtrlFile = $"fun_b0_m{id}_0{part}{MtrlExtension}"; } else if (itemModel.ItemCategory.Equals(XivStrings.Furniture_Outdoor)) { mtrlFolder = $"bgcommon/hou/outdoor/general/{id}/material"; mtrlFile = $"gar_b0_m{id}_0{part}{MtrlExtension}"; } break; default: mtrlFolder = ""; mtrlFile = ""; break; } return(mtrlFolder, mtrlFile, hasVfx); }
private void ItemList_ItemSelected(object sender, IItem item) { if (item == null) { return; } SelectedItem = item; var root = item.GetRoot(); TextureMapComboBox.Items.Clear(); ModelTypeComboBox.Items.Clear(); MaterialComboBox.Items.Clear(); if (OptionList.SelectedItem == null) { return; } var modding = new Modding(_gameDirectory); //var modList = modding.GetModList(); var _imc = new Imc(_gameDirectory); int mSet = -1; string metadataFile = null; var models = new List <string>(); var materials = new List <string>(); var textures = new List <string>(); Task.Run(async() => { if (root != null) { // Get ALL THE THINGS // Meta Entries, Models, Materials, Textures, Icons, and VFX Elements. var im = (IItemModel)item; var df = IOUtil.GetDataFileFromPath(root.Info.GetRootFile()); metadataFile = root.Info.GetRootFile(); mSet = await _imc.GetMaterialSetId(im); models = await root.GetModelFiles(); materials = await root.GetMaterialFiles(mSet); textures = await root.GetTextureFiles(mSet); var _tex = new Tex(XivCache.GameInfo.GameDirectory); var icons = await _tex.GetItemIcons(im); foreach (var icon in icons) { textures.Add(icon.Path); } var _atex = new ATex(XivCache.GameInfo.GameDirectory, df); var paths = await _atex.GetAtexPaths(im); foreach (var path in paths) { textures.Add(path.Path); } } else { if (item.GetType() == typeof(XivCharacter)) { // Face Paint/Equipment Decals jank-items. Ugh. if (item.SecondaryCategory == XivStrings.Face_Paint) { var _character = new Character(XivCache.GameInfo.GameDirectory, XivCache.GameInfo.GameLanguage); var paths = await _character.GetDecalPaths(Character.XivDecalType.FacePaint); foreach (var path in paths) { textures.Add(path); } } else if (item.SecondaryCategory == XivStrings.Equipment_Decals) { var _character = new Character(XivCache.GameInfo.GameDirectory, XivCache.GameInfo.GameLanguage); var paths = await _character.GetDecalPaths(Character.XivDecalType.Equipment); foreach (var path in paths) { textures.Add(path); } } } else { // This is a UI item or otherwise an item which has no root, and only has textures. var uiItem = (XivUi)item; var paths = await uiItem.GetTexPaths(); foreach (var kv in paths) { textures.Add(kv.Value); } } } }).Wait(); MetadataPathBox.Text = metadataFile; foreach (var file in models) { var fe = new FileEntry(); fe.Path = file; fe.Name = MakeFriendlyFileName(file); ModelTypeComboBox.Items.Add(fe); } foreach (var file in materials) { var fe = new FileEntry(); fe.Path = file; fe.Name = MakeFriendlyFileName(file); MaterialComboBox.Items.Add(fe); } foreach (var file in textures) { var fe = new FileEntry(); fe.Path = file; fe.Name = MakeFriendlyFileName(file); TextureMapComboBox.Items.Add(fe); } if (String.IsNullOrEmpty(metadataFile)) { AddMetadataButton.IsEnabled = false; } else { AddMetadataButton.IsEnabled = true; } if (TextureMapComboBox.Items.Count > 0) { AddCurrentTextureButton.IsEnabled = true; AddCustomTextureButton.IsEnabled = true; TextureMapComboBox.SelectedIndex = 0; } else { AddCurrentTextureButton.IsEnabled = false; AddCustomTextureButton.IsEnabled = false; } if (ModelTypeComboBox.Items.Count > 0) { AddCurrentModelButton.IsEnabled = true; AdvOptionsButton.IsEnabled = true; ModelTypeComboBox.SelectedIndex = 0; } else { AddCurrentModelButton.IsEnabled = false; AdvOptionsButton.IsEnabled = false; } if (MaterialComboBox.Items.Count > 0) { AddCurrentMaterialButton.IsEnabled = true; MaterialComboBox.SelectedIndex = 0; } else { AddCurrentMaterialButton.IsEnabled = false; } SelectModGroup.IsEnabled = true; }
public async Task DisableMod() { _view.SaveButton.IsEnabled = false; _view.CancelButton.IsEnabled = false; _view.DisableButton.IsEnabled = false; _view.DisableButton.Content = UIStrings.Working_Ellipsis; var files = new HashSet <string>(); var root = _item.GetRoot(); if (root == null || !Imc.UsesImc(root)) { // This is the only copy of the material we know how to find. files.Add(_material.MTRLPath); } else { var imc = new Imc(XivCache.GameInfo.GameDirectory); var info = await imc.GetFullImcInfo(_item); var entries = info.GetAllEntries(root.Info.Slot); var materialSets = entries.Select(x => x.MaterialSet).ToHashSet(); var extract = new Regex("(v[0-9]{4})"); var rep = extract.Match(_material.MTRLPath).Groups[1].Value; // Remove the material in all of the referenced material sets. foreach (var setId in materialSets) { var newPath = _material.MTRLPath.Replace(rep, "v" + setId.ToString().PadLeft(4, '0')); files.Add(newPath); } } try { foreach (var file in files) { var modEntry = await _modding.TryGetModEntry(file); if (modEntry == null) { continue; } // If the file is a custom addition, and not a modification. if (modEntry.IsCustomFile()) { await _modding.DeleteMod(file); } else { await _modding.ToggleModStatus(file, false); } } } catch (Exception ex) { FlexibleMessageBox.Show("Unable to delete Mod.\n\nError: " + ex.Message, "Mod Delete Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } _view.Close(false); }
/// <summary> /// Gets the available races that contain texture data for the given gear /// </summary> /// <remarks> /// This checks to see if the mtrl file for each race exists in the mtrl folder /// It creates a list of the races which do have an available mtrl folder /// </remarks> /// <param name="xivGear">A gear item</param> /// <returns>A list of XivRace data</returns> public async Task <List <XivRace> > GetRacesForTextures(XivGear xivGear, XivDataFile dataFile) { // Get the material version for the item from the imc file var imc = new Imc(_gameDirectory); var gearVersion = (await imc.GetImcInfo(xivGear)).Variant.ToString().PadLeft(4, '0'); var modelID = xivGear.ModelInfo.PrimaryID.ToString().PadLeft(4, '0'); var raceList = new List <XivRace>(); var itemType = ItemType.GetPrimaryItemType(xivGear); string mtrlFolder; if (itemType == XivItemType.weapon) { return(new List <XivRace> { XivRace.All_Races }); } switch (itemType) { case XivItemType.equipment: mtrlFolder = $"chara/{itemType}/e{modelID}/material/v{gearVersion}"; break; case XivItemType.accessory: mtrlFolder = $"chara/{itemType}/a{modelID}/material/v{gearVersion}"; break; default: mtrlFolder = ""; break; } var testFilesDictionary = new Dictionary <int, string>(); // loop through each race ID to create a dictionary containing [Hashed file name, race ID] foreach (var ID in IDRaceDictionary.Keys) { string mtrlFile; switch (itemType) { case XivItemType.equipment: mtrlFile = $"mt_c{ID}e{modelID}_{xivGear.GetItemSlotAbbreviation()}_a.mtrl"; break; case XivItemType.accessory: mtrlFile = $"mt_c{ID}a{modelID}_{xivGear.GetItemSlotAbbreviation()}_a.mtrl"; break; default: mtrlFile = ""; break; } testFilesDictionary.Add(HashGenerator.GetHash(mtrlFile), ID); } // get the list of hashed file names from the mtrl folder var files = await _index.GetAllHashedFilesInFolder(HashGenerator.GetHash(mtrlFolder), dataFile); // Loop through each entry in the dictionary foreach (var testFile in testFilesDictionary) { // if the file in the dictionary entry is contained in the list of files from the folder // add that race to the race list if (files.Contains(testFile.Key)) { raceList.Add(IDRaceDictionary[testFile.Value]); } } return(raceList); }
/// <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)); }
/// <summary> /// Applies multiple metadata mods simultaneously for performance gains. /// </summary> /// <param name="data"></param> /// <param name="index"></param> /// <param name="modlist"></param> /// <returns></returns> internal static async Task ApplyMetadataBatched(List <ItemMetadata> data, IndexFile index, ModList modlist, bool save = true) { if (data == null || data.Count == 0) { return; } var _eqp = new Eqp(XivCache.GameInfo.GameDirectory); var _modding = new Modding(XivCache.GameInfo.GameDirectory); var _index = new Index(XivCache.GameInfo.GameDirectory); var dummyItem = new XivGenericItemModel(); dummyItem.Name = Constants.InternalModSourceName; dummyItem.SecondaryCategory = Constants.InternalModSourceName; Dictionary <XivRace, List <(uint PrimaryId, string Slot, EquipmentDeformationParameter Entry)> > eqdpEntries = new Dictionary <XivRace, List <(uint PrimaryId, string Slot, EquipmentDeformationParameter Entry)> >(); Dictionary <Est.EstType, List <ExtraSkeletonEntry> > estEntries = new Dictionary <Est.EstType, List <ExtraSkeletonEntry> >(); List <(uint PrimaryId, EquipmentParameter EqpData)> eqpEntries = new List <(uint PrimaryId, EquipmentParameter EqpData)>(); List <(uint PrimaryId, GimmickParameter GmpData)> gmpEntries = new List <(uint PrimaryId, GimmickParameter GmpData)>(); foreach (var meta in data) { // Construct the parameter collections for each function call. foreach (var kv in meta.EqdpEntries) { if (!eqdpEntries.ContainsKey(kv.Key)) { eqdpEntries.Add(kv.Key, new List <(uint PrimaryId, string Slot, EquipmentDeformationParameter Entry)>()); } eqdpEntries[kv.Key].Add(((uint)meta.Root.Info.PrimaryId, meta.Root.Info.Slot, kv.Value)); } var estType = Est.GetEstType(meta.Root); foreach (var kv in meta.EstEntries) { if (!estEntries.ContainsKey(estType)) { estEntries.Add(estType, new List <ExtraSkeletonEntry>()); } estEntries[estType].Add(kv.Value); } if (meta.EqpEntry != null) { eqpEntries.Add(((uint)meta.Root.Info.PrimaryId, meta.EqpEntry)); } if (meta.GmpEntry != null) { gmpEntries.Add(((uint)meta.Root.Info.PrimaryId, meta.GmpEntry)); } } if (index.DataFile == XivDataFile._04_Chara) { // Batch install functions for these three. await _eqp.SaveEqpEntries(eqpEntries, dummyItem, index, modlist); await _eqp.SaveEqdpEntries(eqdpEntries, dummyItem, index, modlist); await _eqp.SaveGmpEntries(gmpEntries, dummyItem, index, modlist); // The EST function already does batch applications by nature of how it works, // so just call it once for each of the four EST types represented. foreach (var kv in estEntries) { await Est.SaveExtraSkeletonEntries(kv.Key, kv.Value, dummyItem, index, modlist); } } // IMC Files don't really overlap that often, so it's // not a significant loss generally to just write them individually. foreach (var meta in data) { if (meta.ImcEntries.Count > 0) { var _imc = new Imc(XivCache.GameInfo.GameDirectory); var imcPath = meta.Root.GetRawImcFilePath(); await _imc.SaveEntries(imcPath, meta.Root.Info.Slot, meta.ImcEntries, null, index, modlist); } } if (save) { await _index.SaveIndexFile(index); await _modding.SaveModListAsync(modlist); } }
public static void CadastrarImc(Imc p) { ctx.TAB_IMC.Add(p); ctx.SaveChanges(); }
/// <summary> /// Gets the mtrl folder for a given item /// </summary> /// <param name="itemModel">Item that contains model data</param> /// <param name="xivRace">The race for the requested data</param> /// <param name="itemType">The type of the item</param> /// <returns>The mtrl Folder</returns> private string GetMtrlFolder(IItemModel itemModel, XivRace xivRace, XivItemType itemType) { // The default version number var version = "0001"; if (itemType != XivItemType.human && itemType != XivItemType.furniture) { // get the items version from the imc file var imc = new Imc(_gameDirectory, _dataFile); var imcInfo = imc.GetImcInfo(itemModel, itemModel.ModelInfo); version = imcInfo.Version.ToString().PadLeft(4, '0'); } if (version.Equals("0000")) { version = "0001"; } var id = itemModel.ModelInfo.ModelID.ToString().PadLeft(4, '0'); var bodyVer = itemModel.ModelInfo.Body.ToString().PadLeft(4, '0'); var race = xivRace.GetRaceCode(); var mtrlFolder = ""; switch (itemType) { case XivItemType.equipment: mtrlFolder = $"chara/{itemType}/e{id}/material/v{version}"; break; case XivItemType.accessory: mtrlFolder = $"chara/{itemType}/a{id}/material/v{version}"; break; case XivItemType.weapon: mtrlFolder = $"chara/{itemType}/w{id}/obj/body/b{bodyVer}/material/v{version}"; break; case XivItemType.monster: mtrlFolder = $"chara/{itemType}/m{id}/obj/body/b{bodyVer}/material/v{version}"; break; case XivItemType.demihuman: mtrlFolder = $"chara/{itemType}/d{id}/obj/equipment/e{bodyVer}/material/v{version}"; break; case XivItemType.human: if (itemModel.ItemCategory.Equals(XivStrings.Body)) { mtrlFolder = $"chara/{itemType}/c{race}/obj/body/b{bodyVer}/material"; } else if (itemModel.ItemCategory.Equals(XivStrings.Hair)) { // Hair has a version number, but no IMC, so we leave it at the default 0001 mtrlFolder = $"chara/{itemType}/c{race}/obj/hair/h{bodyVer}/material/v{version}"; } else if (itemModel.ItemCategory.Equals(XivStrings.Face)) { mtrlFolder = $"chara/{itemType}/c{race}/obj/face/f{bodyVer}/material"; } else if (itemModel.ItemCategory.Equals(XivStrings.Tail)) { mtrlFolder = $"chara/{itemType}/c{race}/obj/tail/t{bodyVer}/material"; } break; case XivItemType.furniture: if (itemModel.ItemCategory.Equals(XivStrings.Furniture_Indoor)) { mtrlFolder = $"bgcommon/hou/indoor/general/{id}/material"; } else if (itemModel.ItemCategory.Equals(XivStrings.Furniture_Outdoor)) { mtrlFolder = $"bgcommon/hou/outdoor/general/{id}/material"; } break; default: mtrlFolder = ""; break; } return(mtrlFolder); }
public async Task SetFile(string filePath) { await LockUi(); WarningLabel.Text = ""; _path = filePath; ChildFilesBox.Items.Clear(); ParentFilesBox.Items.Clear(); SiblingFilesBox.Items.Clear(); AffectedItemsBox.Items.Clear(); ModelLevelBox.Text = ""; MaterialLevelBox.Text = ""; FilePathLabel.Text = filePath; FileNameBox.Text = Path.GetFileName(filePath); var root = await XivCache.GetFirstRoot(filePath); if (root == null) { RootNameBox.Text = "NULL"; WarningLabel.Text = "File dependency information not supported for this item."; await UnlockUi(); return; } RootNameBox.Text = root.ToRawItem().Name; var ext = Path.GetExtension(filePath).Substring(1); var allItems = (await root.GetAllItems()); if (allItems.Count == 0) { WarningLabel.Text = "File dependency information not supported for this item."; await UnlockUi(); return; } if (root.Info.PrimaryType == XivItemType.human) { WarningLabel.Text = "Parent file references & affected items lists \n may not be complete for this file. \n (Unknown cross-references may exist.)"; } var orderedItems = allItems.OrderBy((x => x.Name), new ItemNameComparer()).ToList(); var modelItem = orderedItems[0]; ModelLevelBox.Text = modelItem.Name; var children = await XivCache.GetChildFiles(filePath); var parents = await XivCache.GetParentFiles(filePath); var siblings = await XivCache.GetSiblingFiles(filePath); foreach (var s in children) { ChildFilesBox.Items.Add(s); } foreach (var s in parents) { ParentFilesBox.Items.Add(s); } foreach (var s in siblings) { SiblingFilesBox.Items.Add(s); } Dictionary <XivDependencyRoot, HashSet <int> > mVariants = new Dictionary <XivDependencyRoot, HashSet <int> >(); var affectedItems = new List <IItem>(); if (ext == "tex") { foreach (var parent in parents) { // Each of our parents has a root... var pRoot = await XivCache.GetFirstRoot(parent); if (pRoot == null) { continue; } // And each of these files also has a material set id. var match = _extractVariant.Match(parent); var mVariant = 0; if (match.Success) { mVariant = Int32.Parse(match.Groups[1].Value); } if (!mVariants.ContainsKey(pRoot)) { mVariants.Add(pRoot, new HashSet <int>()); } mVariants[pRoot].Add(mVariant); var pItems = (await pRoot.GetAllItems()); } } else if (ext == "mtrl") { var match = _extractVariant.Match(filePath); var mVariant = 0; if (match.Success) { mVariant = Int32.Parse(match.Groups[1].Value); } if (!mVariants.ContainsKey(root)) { mVariants.Add(root, new HashSet <int>()); } mVariants[root].Add(mVariant); } else { foreach (var item in allItems) { affectedItems.Add(item); } MaterialLevelBox.Text = ""; } Dictionary <XivDependencyRoot, HashSet <int> > sharedImcSubsets = new Dictionary <XivDependencyRoot, HashSet <int> >(); var _imc = new Imc(XivCache.GameInfo.GameDirectory); try { // We now have a dictionary of <Root>, <Material Set Id> that comprises all of our referencing material sets. // We now need to convert that into a list of <root> => <Imc Subset IDs>, for all IMC subsets in that root which use our material ID. foreach (var kv in mVariants) { var rt = kv.Key; sharedImcSubsets.Add(rt, new HashSet <int>()); var imcPath = rt.GetRawImcFilePath(); var fullImcInfo = await _imc.GetFullImcInfo(imcPath); var setCount = fullImcInfo.SubsetCount + 1; for (int i = 0; i < setCount; i++) { var info = fullImcInfo.GetEntry(i, rt.Info.Slot); // This IMC subset references the one of our material sets. if (kv.Value.Contains(info.Variant)) { sharedImcSubsets[rt].Add(i); } } } // We now have a dictionary of <root>, <imc subset ids>. At this point, we can compare this to our original alll items list. var sh = allItems.Where(x => { var iRoot = x.GetRoot(); // The root must be one of our roots we care about. if (!sharedImcSubsets.ContainsKey(iRoot)) { return(false); } var imcs = sharedImcSubsets[iRoot]; // The imc subset must be in the imc subsets that use this material. if (!imcs.Contains(x.ModelInfo.ImcSubsetID)) { return(false); } return(true); }); foreach (var i in sh) { affectedItems.Add(i); } } catch { // The item doesn't have a valid IMC entry. In that case, it affects all items in the tree. affectedItems.AddRange(allItems); } if (affectedItems.Count == 0) { MaterialLevelBox.Text = "Unknown"; } else { if (ext == "tex" || ext == "mtrl") { var ordered = affectedItems.OrderBy((x => x.Name), new ItemNameComparer()).ToList(); MaterialLevelBox.Text = ordered[0].Name; } } foreach (var item in affectedItems) { AffectedItemsBox.Items.Add(item); } await UnlockUi(); }
/// <summary> /// Updates the View/ViewModel with a new selected base item. /// </summary> /// <param name="item"></param> /// <returns></returns> public async Task <bool> SetItem(IItem item, MainWindow mainWindow = null) { var gameDirectory = new DirectoryInfo(Properties.Settings.Default.FFXIV_Directory); _imc = new Imc(gameDirectory, item.DataFile); _gear = new Gear(gameDirectory, XivLanguages.GetXivLanguage(Properties.Settings.Default.Application_Language)); if (mainWindow != null) { _mainWindow = mainWindow; } _item = item; _tree.Items.Clear(); IItemModel im = null; try { im = (IItemModel)item; } catch (Exception ex) { return(false); } if (im == null || im.ModelInfo == null) { return(false); } var topLevelItem = new TreeViewItem(); topLevelItem.Header = ""; if (im.ModelInfo.PrimaryID > 0) { topLevelItem.Header += CapFirst(item.GetPrimaryItemType().ToString()) + " #" + im.ModelInfo.PrimaryID.ToString().PadLeft(4, '0'); } else { topLevelItem.Header += CapFirst(item.GetPrimaryItemType().ToString()); } _tree.Items.Add(topLevelItem); var nextParent = topLevelItem; if (im.ModelInfo.SecondaryID > 0) { var nextNode = new TreeViewItem(); nextNode.Header += CapFirst(item.GetSecondaryItemType().ToString()) + " #" + im.ModelInfo.SecondaryID.ToString().PadLeft(4, '0'); nextParent.Items.Add(nextNode); nextParent.IsExpanded = true; nextParent = nextNode; } var abbreviation = _item.GetItemSlotAbbreviation(); if (abbreviation != "") { var nextNode = new TreeViewItem(); nextNode.Header = Mdl.SlotAbbreviationDictionary.First(x => x.Value == abbreviation).Key; nextParent.Items.Add(nextNode); nextParent.IsExpanded = true; nextParent = nextNode; } FullImcInfo fullInfo = null; try { fullInfo = await _imc.GetFullImcInfo(im); } catch (Exception ex) { // This item has no IMC file. var nextNode = new TreeViewItem(); nextNode.Header = im.Name; nextNode.DataContext = im; //nextNode.MouseDoubleClick += ItemNode_Activated; nextParent.Items.Add(nextNode); nextParent.IsExpanded = true; nextNode.IsSelected = true; nextParent = nextNode; // No shared items for things without IMC files, so just hide the view entirely? return(false); } var sharedList = await _gear.GetSameModelList(im); var myVariantNumber = fullInfo.GetEntry(im.ModelInfo.ImcSubsetID, im.GetItemSlotAbbreviation()).Variant; var myImcNumber = im.ModelInfo.ImcSubsetID; var materialVariantHeaders = new Dictionary <int, TreeViewItem>(); var imcVariantHeaders = new Dictionary <int, TreeViewItem>(); // TODO - // Add the Variant header nodes at the start, and only scan the IMC files when a TreeViewItem myMaterialHeader = null; TreeViewItem myImcHeader = null; TreeViewItem myNode = null; foreach (var i in sharedList) { // Get the Variant # information var info = fullInfo.GetEntry(i.ModelInfo.ImcSubsetID, i.GetItemSlotAbbreviation()); if (info == null) { // Invalid IMC Set ID for the item. continue; } if (!materialVariantHeaders.ContainsKey(info.Variant)) { materialVariantHeaders.Add(info.Variant, new TreeViewItem()); materialVariantHeaders[info.Variant].Header = "Material Variant #" + info.Variant; materialVariantHeaders[info.Variant].DataContext = info.Variant; } if (!imcVariantHeaders.ContainsKey(i.ModelInfo.ImcSubsetID)) { imcVariantHeaders.Add(i.ModelInfo.ImcSubsetID, new TreeViewItem()); imcVariantHeaders[i.ModelInfo.ImcSubsetID].Header = "IMC Variant #" + i.ModelInfo.ImcSubsetID; imcVariantHeaders[i.ModelInfo.ImcSubsetID].DataContext = i.ModelInfo.ImcSubsetID; var hiddenParts = MaskToHidenParts(info.Mask); imcVariantHeaders[i.ModelInfo.ImcSubsetID].Header += " - Hidden Parts: "; if (hiddenParts.Count > 0) { imcVariantHeaders[i.ModelInfo.ImcSubsetID].Header += String.Join(",", hiddenParts); } else { imcVariantHeaders[i.ModelInfo.ImcSubsetID].Header += "None"; } materialVariantHeaders[info.Variant].Items.Add(imcVariantHeaders[i.ModelInfo.ImcSubsetID]); if (i.ModelInfo.ImcSubsetID == myImcNumber) { myImcHeader = imcVariantHeaders[i.ModelInfo.ImcSubsetID]; } } var nextNode = new TreeViewItem(); nextNode.Header = i.Name; nextNode.DataContext = i; imcVariantHeaders[i.ModelInfo.ImcSubsetID].Items.Add(nextNode); if (myMaterialHeader == null && info.Variant == myVariantNumber) { myMaterialHeader = materialVariantHeaders[info.Variant]; } if (i.Name == im.Name) { myNode = nextNode; } else { nextNode.MouseDoubleClick += ItemNode_Activated; } } var ordered = materialVariantHeaders.OrderBy(x => x.Key); foreach (var kv in ordered) { nextParent.Items.Add(kv.Value); } nextParent.IsExpanded = true; if (myMaterialHeader != null) { myMaterialHeader.IsExpanded = true; } if (myImcHeader != null) { myImcHeader.IsExpanded = true; } if (myNode != null) { myNode.IsSelected = true; } return(true); }
/// <summary> /// Gets the list of available mtrl parts for a given item /// </summary> /// <param name="itemModel">An item that contains model data</param> /// <param name="xivRace">The race for the requested data</param> /// <returns>A list of part characters</returns> public List <string> GetTexturePartList(IItemModel itemModel, XivRace xivRace, XivDataFile dataFile) { // Get the mtrl version for the given item from the imc file var imc = new Imc(_gameDirectory, dataFile); var version = imc.GetImcInfo(itemModel, itemModel.PrimaryModelInfo).Version.ToString().PadLeft(4, '0'); var id = itemModel.PrimaryModelInfo.ModelID.ToString().PadLeft(4, '0'); var bodyVer = itemModel.PrimaryModelInfo.Body.ToString().PadLeft(4, '0'); var parts = new[] { 'a', 'b', 'c', 'd', 'e', 'f' }; var race = xivRace.GetRaceCode(); var index = new Index(_gameDirectory); var itemType = ItemType.GetItemType(itemModel); string mtrlFolder = "", mtrlFile = ""; switch (itemType) { case XivItemType.equipment: mtrlFolder = $"chara/{itemType}/e{id}/material/v{version}"; mtrlFile = $"mt_c{race}e{id}_{SlotAbbreviationDictionary[itemModel.ItemCategory]}_"; break; case XivItemType.accessory: mtrlFolder = $"chara/{itemType}/a{id}/material/v{version}"; mtrlFile = $"mt_c{race}a{id}_{SlotAbbreviationDictionary[itemModel.ItemCategory]}_"; break; case XivItemType.weapon: mtrlFolder = $"chara/{itemType}/w{id}/obj/body/b{bodyVer}/material/v{version}"; mtrlFile = $"mt_w{id}b{bodyVer}_"; break; case XivItemType.monster: mtrlFolder = $"chara/{itemType}/m{id}/obj/body/b{bodyVer}/material/v{version}"; mtrlFile = $"mt_m{id}b{bodyVer}_"; break; case XivItemType.demihuman: mtrlFolder = $"chara/{itemType}/d{id}/obj/body/e{bodyVer}/material/v{version}"; mtrlFile = $"mt_d{id}e{bodyVer}_"; break; case XivItemType.human: if (itemModel.ItemCategory.Equals(XivStrings.Body)) { mtrlFolder = $"chara/{itemType}/c{id}/obj/body/b{bodyVer}/material/v{version}"; mtrlFile = $"mt_c{id}b{bodyVer}_"; } else if (itemModel.ItemCategory.Equals(XivStrings.Hair)) { mtrlFolder = $"chara/{itemType}/c{id}/obj/body/h{bodyVer}/material/v{version}"; mtrlFile = $"mt_c{id}h{bodyVer}_{SlotAbbreviationDictionary[itemModel.ItemCategory]}_"; } else if (itemModel.ItemCategory.Equals(XivStrings.Face)) { mtrlFolder = $"chara/{itemType}/c{id}/obj/body/f{bodyVer}/material/v{version}"; mtrlFile = $"mt_c{id}f{bodyVer}_{SlotAbbreviationDictionary[itemModel.ItemCategory]}_"; } else if (itemModel.ItemCategory.Equals(XivStrings.Tail)) { mtrlFolder = $"chara/{itemType}/c{id}/obj/body/t{bodyVer}/material/v{version}"; mtrlFile = $"mt_c{id}t{bodyVer}_"; } break; default: mtrlFolder = ""; break; } // Get a list of hashed mtrl files that are in the given folder var files = index.GetAllHashedFilesInFolder(HashGenerator.GetHash(mtrlFolder), dataFile); // append the part char to the mtrl file and see if its hashed value is within the files list // returns the list of parts that exist within the mtrl folder return((from part in parts let mtrlCheck = mtrlFile + part + ".mtrl" where files.Contains(HashGenerator.GetHash(mtrlCheck)) select part.ToString()).ToList()); }
private void btnCalcularImc_Click(object sender, RoutedEventArgs e) { txtImc.Text = "IMC= "; if (txtAltura.Text != "" && txtPeso.Text != "") { double altura = Convert.ToDouble(txtAltura.Text); double peso = Convert.ToDouble(txtPeso.Text); string resultado = ""; altura = altura * altura; peso = peso / altura; txtImc.Text += peso.ToString("F2"); if (peso >= 40) { resultado = "Obesidade de nível 3"; } else if (peso >= 35 && peso <= 39) { resultado = "Obesidade de nível 2"; } else if (peso >= 30 && peso <= 34) { resultado = "Obesidade de nível 1"; } else if (peso >= 25 && peso <= 29) { resultado = "Sobrepeso"; } else if (peso >= 18 && peso <= 24) { resultado = "Peso normal"; } else if (peso <= 17) { resultado = "Magreza"; } Aluno a = AlunoDAO.BuscarNomeSenha(Login.cpfLogin, Login.senhaLogin); Imc i = new Imc(); i.altura = Convert.ToDouble(txtAltura.Text); i.peso = Convert.ToDouble(txtPeso.Text); if (a != null) { i.aluno = a; } else { MessageBox.Show("Deu ruim"); } i.imcResult = peso.ToString("F2"); i.resultado = resultado; ImcDAO.CadastrarImc(i); int idImc = Convert.ToInt32(i.idImc); i = ImcDAO.BuscarId(idImc); dynamic d = new { peso = i.peso, altura = i.altura, criadoEm = i.criadoEm, imcResult = i.imcResult, resultado = i.resultado }; imcGrid.Add(d); cboImc.ItemsSource = imcGrid; cboImc.Items.Refresh(); } else { MessageBox.Show("Prencha os campos", "Erro"); } }
public async Task SaveMulti() { var _imc = new Imc(XivCache.GameInfo.GameDirectory); var _index = new Index(XivCache.GameInfo.GameDirectory); // Get tokenized map info structs. // This will let us set them in the new Materials and // Detokenize them using the new paths. var mapInfos = _material.GetAllMapInfos(true); // Shader info likewise will be pumped into each new material. var shaderInfo = _material.GetShaderInfo(); // Add new Materials for shared model items. var oldMaterialIdentifier = _material.GetMaterialIdentifier(); var oldMtrlName = Path.GetFileName(_material.MTRLPath); // Ordering these by name ensures that we create textures for the new variants in the first // item alphabetically, just for consistency's sake. var sameModelItems = (await _item.GetSharedModelItems()).OrderBy(x => x.Name, new ItemNameComparer()); var oldVariantString = "/v" + _material.GetVariant().ToString().PadLeft(4, '0') + '/'; var modifiedVariants = new List <int>(); var mtrlReplacementRegex = "_" + oldMaterialIdentifier + ".mtrl"; var mtrlReplacementRegexResult = "_" + _newMaterialIdentifier + ".mtrl"; if (_mode == MaterialEditorMode.NewRace) { mtrlReplacementRegexResult = mtrlReplacementRegex; } var newMtrlName = oldMtrlName.Replace(mtrlReplacementRegex, mtrlReplacementRegexResult); var root = _item.GetRootInfo(); var imcEntries = new List <XivImc>(); var materialSets = new HashSet <byte>(); try { var imcInfo = await _imc.GetFullImcInfo(_item); imcEntries = imcInfo.GetAllEntries(root.Slot, true); materialSets = imcEntries.Select(x => x.MaterialSet).ToHashSet(); } catch { // Item doesn't use IMC entries, and thus only has a single variant. materialSets.Clear(); materialSets.Add(0); } // We need to save our non-existent base material once before we can continue. if (_mode == MaterialEditorMode.NewRace) { await _mtrl.ImportMtrl(_material, _item, XivStrings.TexTools); } var count = 0; var allItems = (await root.ToFullRoot().GetAllItems()); var matNumToItems = new Dictionary <int, List <IItemModel> >(); foreach (var i in allItems) { if (imcEntries.Count <= i.ModelInfo.ImcSubsetID) { continue; } var matSet = imcEntries[i.ModelInfo.ImcSubsetID].MaterialSet; if (!matNumToItems.ContainsKey(matSet)) { matNumToItems.Add(matSet, new List <IItemModel>()); } var saveItem = i; if (typeof(XivCharacter) == i.GetType()) { var temp = (XivCharacter)((XivCharacter)_item).Clone(); temp.Name = saveItem.SecondaryCategory; saveItem = temp; } matNumToItems[matSet].Add(saveItem); } var keys = matNumToItems.Keys.ToList(); foreach (var key in keys) { var list = matNumToItems[key]; matNumToItems[key] = list.OrderBy(x => x.Name, new ItemNameComparer()).ToList(); } // Load and modify all the MTRLs. foreach (var materialSetId in materialSets) { var variantPath = _mtrl.GetMtrlFolder(root, materialSetId); var oldMaterialPath = variantPath + "/" + oldMtrlName; var newMaterialPath = variantPath + "/" + newMtrlName; // Don't create materials for set 0. (SE sets the material ID to 0 when that particular set-slot doesn't actually exist as an item) if (materialSetId == 0 && imcEntries.Count > 0) { continue; } var dxVersion = 11; XivMtrl itemXivMtrl; // Get mtrl path if (await _index.FileExists(oldMaterialPath)) { // Use the Material from this variant as a base? itemXivMtrl = await _mtrl.GetMtrlData(_item, oldMaterialPath, dxVersion); } else { itemXivMtrl = await _mtrl.GetMtrlData(_item, _material.MTRLPath, dxVersion); } // If we're an item that doesn't use IMC variants, make sure we don't accidentally move the material around. if (materialSetId != 0) { // Shift the MTRL to the new variant folder. itemXivMtrl.MTRLPath = Regex.Replace(itemXivMtrl.MTRLPath, oldVariantString, "/v" + materialSetId.ToString().PadLeft(4, '0') + "/"); } if (_mode == MaterialEditorMode.NewMulti) { // Change the MTRL part identifier. itemXivMtrl.MTRLPath = Regex.Replace(itemXivMtrl.MTRLPath, mtrlReplacementRegex, mtrlReplacementRegexResult); } // Load the Shader Settings itemXivMtrl.SetShaderInfo(shaderInfo, true); // Loop our tokenized map infos and pump them back in // using the new modified material to detokenize them. foreach (var info in mapInfos) { itemXivMtrl.SetMapInfo(info.Usage, (MapInfo)info.Clone()); } IItem item; try { item = matNumToItems[materialSetId].First(); } catch { item = (await XivCache.GetFirstRoot(itemXivMtrl.MTRLPath)).GetFirstItem(); } count++; // Write the new Material await _mtrl.ImportMtrl(itemXivMtrl, item, XivStrings.TexTools); _view.SaveStatusLabel.Content = "Updated " + count + "/" + materialSets.Count + " Material Sets..."; } }
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)); } } } }
/// <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; } }
/// <summary> /// Applies this Metadata object to the FFXIV file system. /// This should only called by Dat.WriteToDat() / RestoreDefaultMetadata() /// </summary> internal static async Task ApplyMetadata(ItemMetadata meta, IndexFile index = null, ModList modlist = null) { var _eqp = new Eqp(XivCache.GameInfo.GameDirectory); var _modding = new Modding(XivCache.GameInfo.GameDirectory); var _index = new Index(XivCache.GameInfo.GameDirectory); var df = IOUtil.GetDataFileFromPath(meta.Root.Info.GetRootFile()); var dummyItem = new XivGenericItemModel(); dummyItem.Name = Constants.InternalModSourceName; dummyItem.SecondaryCategory = Constants.InternalModSourceName; // Beep boop bool doSave = false; if (index == null) { doSave = true; index = await _index.GetIndexFile(df); modlist = await _modding.GetModListAsync(); } if (meta.ImcEntries.Count > 0) { var _imc = new Imc(XivCache.GameInfo.GameDirectory); var imcPath = meta.Root.GetRawImcFilePath(); await _imc.SaveEntries(imcPath, meta.Root.Info.Slot, meta.ImcEntries, dummyItem, index, modlist); } // Applying EQP data via set 0 is not allowed, as it is a special set hard-coded to use Set 1's data. if (meta.EqpEntry != null && !(meta.Root.Info.PrimaryType == Items.Enums.XivItemType.equipment && meta.Root.Info.PrimaryId == 0)) { await _eqp.SaveEqpEntry(meta.Root.Info.PrimaryId, meta.EqpEntry, dummyItem, index, modlist); } if (meta.EqdpEntries.Count > 0) { await _eqp.SaveEqdpEntries((uint)meta.Root.Info.PrimaryId, meta.Root.Info.Slot, meta.EqdpEntries, dummyItem, index, modlist); } if (meta.EstEntries.Count > 0) { var type = Est.GetEstType(meta.Root); var entries = meta.EstEntries.Values.ToList(); await Est.SaveExtraSkeletonEntries(type, entries, dummyItem, index, modlist); } if (meta.GmpEntry != null) { await _eqp.SaveGimmickParameter(meta.Root.Info.PrimaryId, meta.GmpEntry, dummyItem, index, modlist); } if (doSave) { await _index.SaveIndexFile(index); await _modding.SaveModListAsync(modlist); } }
/// <summary> /// Gets the list of available mtrl parts for a given item /// </summary> /// <param name="itemModel">An item that contains model data</param> /// <param name="xivRace">The race for the requested data</param> /// <returns>A list of part characters</returns> public async Task <List <string> > GetTexturePartList(IItemModel itemModel, XivRace xivRace, XivDataFile dataFile, string type = "Primary") { var itemType = ItemType.GetItemType(itemModel); var version = "0001"; var id = itemModel.ModelInfo.ModelID.ToString().PadLeft(4, '0'); var bodyVer = itemModel.ModelInfo.Body.ToString().PadLeft(4, '0'); var itemCategory = itemModel.ItemCategory; if (type.Equals("Secondary")) { var xivGear = itemModel as XivGear; id = xivGear.SecondaryModelInfo.ModelID.ToString().PadLeft(4, '0'); bodyVer = xivGear.SecondaryModelInfo.Body.ToString().PadLeft(4, '0'); var imc = new Imc(_gameDirectory, xivGear.DataFile); version = (await imc.GetImcInfo(itemModel, xivGear.SecondaryModelInfo)).Version.ToString().PadLeft(4, '0'); if (imc.ChangedType) { itemType = XivItemType.equipment; xivRace = XivRace.Hyur_Midlander_Male; itemCategory = XivStrings.Hands; } } else { if (itemType != XivItemType.human && itemType != XivItemType.furniture) { // Get the mtrl version for the given item from the imc file var imc = new Imc(_gameDirectory, dataFile); version = (await imc.GetImcInfo(itemModel, itemModel.ModelInfo)).Version.ToString().PadLeft(4, '0'); } } var parts = new[] { 'a', 'b', 'c', 'd', 'e', 'f' }; var race = xivRace.GetRaceCode(); string mtrlFolder = "", mtrlFile = ""; switch (itemType) { case XivItemType.equipment: mtrlFolder = $"chara/{itemType}/e{id}/material/v{version}"; mtrlFile = $"mt_c{race}e{id}_{SlotAbbreviationDictionary[itemCategory]}_"; break; case XivItemType.accessory: mtrlFolder = $"chara/{itemType}/a{id}/material/v{version}"; mtrlFile = $"mt_c{race}a{id}_{SlotAbbreviationDictionary[itemCategory]}_"; break; case XivItemType.weapon: mtrlFolder = $"chara/{itemType}/w{id}/obj/body/b{bodyVer}/material/v{version}"; mtrlFile = $"mt_w{id}b{bodyVer}_"; break; case XivItemType.monster: mtrlFolder = $"chara/{itemType}/m{id}/obj/body/b{bodyVer}/material/v{version}"; mtrlFile = $"mt_m{id}b{bodyVer}_"; break; case XivItemType.demihuman: mtrlFolder = $"chara/{itemType}/d{id}/obj/body/e{bodyVer}/material/v{version}"; mtrlFile = $"mt_d{id}e{bodyVer}_"; break; case XivItemType.human: if (itemCategory.Equals(XivStrings.Body)) { mtrlFolder = $"chara/{itemType}/c{id}/obj/body/b{bodyVer}/material/v{version}"; mtrlFile = $"mt_c{id}b{bodyVer}_"; } else if (itemCategory.Equals(XivStrings.Hair)) { mtrlFolder = $"chara/{itemType}/c{id}/obj/body/h{bodyVer}/material/v{version}"; mtrlFile = $"mt_c{id}h{bodyVer}_{SlotAbbreviationDictionary[itemCategory]}_"; } else if (itemCategory.Equals(XivStrings.Face)) { mtrlFolder = $"chara/{itemType}/c{id}/obj/body/f{bodyVer}/material/v{version}"; mtrlFile = $"mt_c{id}f{bodyVer}_{SlotAbbreviationDictionary[itemCategory]}_"; } else if (itemCategory.Equals(XivStrings.Tail)) { mtrlFolder = $"chara/{itemType}/c{id}/obj/body/t{bodyVer}/material/v{version}"; mtrlFile = $"mt_c{id}t{bodyVer}_"; } break; case XivItemType.furniture: if (itemCategory.Equals(XivStrings.Furniture_Indoor)) { mtrlFolder = $"bgcommon/hou/indoor/general/{id}/material"; mtrlFile = $"fun_b0_m{id}_0"; } else if (itemCategory.Equals(XivStrings.Furniture_Outdoor)) { mtrlFolder = $"bgcommon/hou/outdoor/general/{id}/material"; mtrlFile = $"gar_b0_m{id}_0"; } break; default: mtrlFolder = ""; break; } // Get a list of hashed mtrl files that are in the given folder var files = await _index.GetAllHashedFilesInFolder(HashGenerator.GetHash(mtrlFolder), dataFile); // append the part char to the mtrl file and see if its hashed value is within the files list var partList = (from part in parts let mtrlCheck = mtrlFile + part + ".mtrl" where files.Contains(HashGenerator.GetHash(mtrlCheck)) select part.ToString()).ToList(); if (partList.Count < 1 && itemType == XivItemType.furniture) { if (itemCategory.Equals(XivStrings.Furniture_Indoor)) { mtrlFile = $"fun_b0_m{id}_1"; } else if (itemCategory.Equals(XivStrings.Furniture_Outdoor)) { mtrlFile = $"gar_b0_m{id}_1"; } // Get a list of hashed mtrl files that are in the given folder files = await _index.GetAllHashedFilesInFolder(HashGenerator.GetHash(mtrlFolder), dataFile); // append the part char to the mtrl file and see if its hashed value is within the files list partList = (from part in parts let mtrlCheck = mtrlFile + part + ".mtrl" where files.Contains(HashGenerator.GetHash(mtrlCheck)) select part.ToString()).ToList(); } // returns the list of parts that exist within the mtrl folder return(partList); }
private async Task LoadItems() { List <string> children = new List <string>(); var root = _item.GetRoot(); if (root != null) { if (_level == XivDependencyLevel.Model) { children = await root.GetModelFiles(); } else if (_level == XivDependencyLevel.Material) { var imc = new Imc(XivCache.GameInfo.GameDirectory); try { var entry = await imc.GetImcInfo((IItemModel)_item); children = await root.GetMaterialFiles(entry.MaterialSet); } catch { if (root.Info.SecondaryType == XivItemType.hair || root.Info.SecondaryType == XivItemType.tail || (root.Info.PrimaryType == XivItemType.human && root.Info.SecondaryType == XivItemType.body)) { // These types don't have IMC entries, but have a material variant number. // Kind of weird, but whatever. children = await root.GetMaterialFiles(1); } else { children = await root.GetMaterialFiles(0); } } } else if (_level == XivDependencyLevel.Texture) { try { var imc = new Imc(XivCache.GameInfo.GameDirectory); var entry = await imc.GetImcInfo((IItemModel)_item); children = await root.GetTextureFiles(entry.MaterialSet); } catch { if (root.Info.SecondaryType == XivItemType.hair || root.Info.SecondaryType == XivItemType.tail || (root.Info.PrimaryType == XivItemType.human && root.Info.SecondaryType == XivItemType.body)) { // These types don't have IMC entries, but have a material variant number. // Kind of weird, but whatever. children = await root.GetTextureFiles(1); } else { children = await root.GetTextureFiles(0); } } } else { // Invalid or root, nothing listed. } } var index = new Index(XivCache.GameInfo.GameDirectory); foreach (var file in children) { var exists = await index.FileExists(file); if (!exists) { continue; } Files.Add(new FileEntry(file)); } }