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 List <string>();

            // If we're disabling from the Edit Multi menu, diable all variant versions as well.
            if (_mode == MaterialEditorMode.EditMulti)
            {
                var sameModelItems = await _item.GetSharedModelItems();

                var itemType = ItemType.GetPrimaryItemType(_item);
                // Find all the variant materials
                foreach (var item in sameModelItems)
                {
                    var variantPath = await _mtrl.GetMtrlPath(item, _material.GetRace(), _material.GetMaterialIdentifier(), itemType);

                    files.Add(variantPath.Folder + "/" + variantPath.File);
                }
            }
            else
            {
                // Just disabling this one.
                files.Add(_material.MTRLPath);
            }

            files = files.Distinct().ToList();

            foreach (var file in files)
            {
                var modEntry = await _modding.TryGetModEntry(file);

                if (!modEntry.enabled)
                {
                    continue;
                }

                // If the file is a custom addition, and not a modification.
                if (modEntry.source != XivStrings.TexTools)
                {
                    await _modding.DeleteMod(file);
                }
                else
                {
                    await _modding.ToggleModStatus(file, false);
                }
            }
            _view.Close(false);
        }
Пример #2
0
        /// <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));
        }
Пример #3
0
        /// <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)
        {
            var atexTexTypePathList = new List <TexTypePath>();

            var index = new Index(_gameDirectory);
            var avfx  = new Avfx(_gameDirectory, _dataFile);

            var itemType = ItemType.GetPrimaryItemType(itemModel);

            var vfxPath = await GetVfxPath(itemModel, itemType);

            var vfxOffset = await index.GetDataOffset(HashGenerator.GetHash(vfxPath.Folder), HashGenerator.GetHash(vfxPath.File),
                                                      _dataFile);

            if (vfxOffset == 0)
            {
                throw new Exception($"Could not find offset for vfx path {vfxPath.Folder}/{vfxPath.File}");
            }

            var aTexPaths = new List <string>();

            try
            {
                aTexPaths = await avfx.GetATexPaths(vfxOffset);
            }
            catch (Exception e)
            {
                throw new Exception(e.Message);
            }

            foreach (var atexPath in aTexPaths)
            {
                var ttp = new TexTypePath
                {
                    DataFile = _dataFile,
                    Name     = "VFX: " + Path.GetFileNameWithoutExtension(atexPath),
                    Path     = atexPath
                };

                atexTexTypePathList.Add(ttp);
            }

            return(atexTexTypePathList);
        }
        public async Task SaveMulti()
        {
            // 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();

            // 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";


            // Load and modify all the MTRLs.
            foreach (var item in sameModelItems)
            {
                // Resolve this item's material variant.
                // - This isn't always the same as the item model variant, for some reason.
                // - So it has to be resolved manually.
                var variantMtrlPath = "";
                var itemType        = ItemType.GetPrimaryItemType(_item);


                variantMtrlPath = (await _mtrl.GetMtrlPath(item, _material.GetRace(), oldMaterialIdentifier, itemType)).Folder;

                var match   = Regex.Match(variantMtrlPath, "/v([0-9]+)");
                var variant = 0;
                if (match.Success)
                {
                    variant = Int32.Parse(match.Groups[1].Value);
                }

                // Only modify each Variant once.
                if (modifiedVariants.Contains(variant))
                {
                    continue;
                }

                var     dxVersion = 11;
                XivMtrl itemXivMtrl;

                // Get mtrl path -- TODO: Need support here for offhand item materials.
                // But Offhand support is basically completely broken anyways, so this can wait.
                itemXivMtrl = await _mtrl.GetMtrlData(_item, _material.GetRace(), oldMaterialIdentifier, dxVersion);

                // Shift the MTRL to the new variant folder.
                itemXivMtrl.MTRLPath = Regex.Replace(itemXivMtrl.MTRLPath, oldVariantString, "/v" + variant.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());
                }

                // Write the new Material
                await _mtrl.ImportMtrl(itemXivMtrl, item, XivStrings.TexTools);

                modifiedVariants.Add(variant);
                _view.SaveStatusLabel.Content = "Updated " + modifiedVariants.Count + " Variants...";
            }
        }
Пример #5
0
        /// <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)
        {
            var itemType = ItemType.GetPrimaryItemType(itemModel);

            var version = "0001";

            var id           = itemModel.ModelInfo.PrimaryID.ToString().PadLeft(4, '0');
            var bodyVer      = itemModel.ModelInfo.SecondaryID.ToString().PadLeft(4, '0');
            var itemCategory = itemModel.SecondaryCategory;

            if (itemType != XivItemType.human && itemType != XivItemType.furniture)
            {
                // Get the mtrl version for the given item from the imc file
                var imc = new Imc(_gameDirectory);
                version = (await imc.GetImcInfo(itemModel)).MaterialSet.ToString().PadLeft(4, '0');
            }

            var parts = Constants.Alphabet;
            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}_{itemModel.GetItemSlotAbbreviation()}_";
                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);
        }
Пример #6
0
        /// <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);
        }