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); }
public async Task <FullImcInfo> GetFullImcInfo(IItemModel item, IndexFile index = null, ModList modlist = null) { FullImcInfo info = null; try { var imcPath = GetImcPath(item); var path = imcPath.Folder + "/" + imcPath.File; info = await GetFullImcInfo(path, index, modlist); } catch { // Some dual wield items don't have a second IMC, and just default to the first. if (typeof(XivGear) == item.GetType()) { var gear = (XivGear)item; if (gear != null && gear.PairedItem != null) { var pair = gear.PairedItem; var imcPath = GetImcPath(pair); var path = imcPath.Folder + "/" + imcPath.File; return(await(GetFullImcInfo(path, index, modlist))); } } else { throw new InvalidDataException("Unable to get IMC data for item: " + item.Name); } } return(info); }
/// <summary> /// Gets the Icon info for a specific gear item /// </summary> /// <param name="gearItem">The gear item</param> /// <returns>A list of TexTypePath containing Icon Info</returns> public async Task <List <TexTypePath> > GetItemIcons(IItemModel iconItem) { var type = iconItem.GetType(); uint iconNumber = 0; if (type == typeof(XivGear)) { iconNumber = ((XivGear)iconItem).IconNumber; } else if (type == typeof(XivFurniture)) { iconNumber = ((XivFurniture)iconItem).IconNumber; } if (iconNumber <= 0) { return(new List <TexTypePath>()); } var iconString = iconNumber.ToString(); var ttpList = new List <TexTypePath>(); var iconBaseNum = iconString.Substring(0, 2).PadRight(iconString.Length, '0'); var iconFolder = $"ui/icon/{iconBaseNum.PadLeft(6, '0')}"; var iconHQFolder = $"{iconFolder}/hq"; var iconFile = $"{iconString.PadLeft(6, '0')}.tex"; var path = iconFolder + "/" + iconFile; if (await _index.FileExists(path, XivDataFile._06_Ui)) { ttpList.Add(new TexTypePath { Name = "Icon", Path = $"{iconFolder}/{iconFile}", Type = XivTexType.Icon, DataFile = XivDataFile._06_Ui }); } path = iconHQFolder + "/" + iconFile; if (await _index.FileExists(path, XivDataFile._06_Ui)) { ttpList.Add(new TexTypePath { Name = "HQ Icon", Path = $"{iconHQFolder}/{iconFile}", Type = XivTexType.Icon, DataFile = XivDataFile._06_Ui }); } return(ttpList); }
/// <summary> /// Gets the atex paths for a given item /// </summary> /// <param name="itemModel">The item to get the atex paths for</param> /// <returns>A list of TexTypePath containing the atex info</returns> public async Task <List <TexTypePath> > GetAtexPaths(IItemModel itemModel) { // Gear is the only type we know how to retrieve atex information for. if (itemModel.GetType() != typeof(XivGear)) { return(new List <TexTypePath>()); } var itemType = ItemType.GetPrimaryItemType(itemModel); var vfxPath = await GetVfxPath(itemModel); return(await GetAtexPaths(vfxPath.Folder + '/' + vfxPath.File)); }
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; } }
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)}"); }